@pennyfarthing/core 11.2.0 → 11.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. package/README.md +100 -40
  2. package/package.json +2 -1
  3. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor.js +474 -66
  5. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  6. package/packages/core/dist/cli/commands/init.js +4 -4
  7. package/packages/core/dist/cli/commands/init.js.map +1 -1
  8. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  9. package/packages/core/dist/cli/commands/update.js +4 -5
  10. package/packages/core/dist/cli/commands/update.js.map +1 -1
  11. package/packages/core/dist/cli/utils/constants.d.ts +3 -8
  12. package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
  13. package/packages/core/dist/cli/utils/constants.js +3 -4
  14. package/packages/core/dist/cli/utils/constants.js.map +1 -1
  15. package/packages/core/dist/cli/utils/settings.d.ts +7 -0
  16. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  17. package/packages/core/dist/cli/utils/settings.js +70 -29
  18. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  19. package/packages/core/dist/cli/utils/symlinks.js +16 -16
  20. package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
  21. package/packages/core/dist/consultation/dialogue-manager.d.ts +1 -1
  22. package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -1
  23. package/packages/core/dist/consultation/dialogue-manager.js +1 -1
  24. package/packages/core/dist/consultation/dialogue-manager.js.map +1 -1
  25. package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -1
  26. package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
  27. package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
  28. package/packages/core/dist/consultation/tandem-metrics.js +131 -0
  29. package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
  30. package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
  31. package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
  32. package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
  33. package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
  34. package/packages/core/dist/public/css/react.css +1 -1
  35. package/packages/core/dist/public/js/react/react.js +14 -14
  36. package/packages/core/dist/server/api/agent-load.js +1 -1
  37. package/packages/core/dist/server/api/agent-load.js.map +1 -1
  38. package/packages/core/dist/server/api/git.d.ts.map +1 -1
  39. package/packages/core/dist/server/api/git.js +0 -1
  40. package/packages/core/dist/server/api/git.js.map +1 -1
  41. package/packages/core/dist/server/api/index.d.ts +2 -0
  42. package/packages/core/dist/server/api/index.d.ts.map +1 -1
  43. package/packages/core/dist/server/api/index.js +2 -0
  44. package/packages/core/dist/server/api/index.js.map +1 -1
  45. package/packages/core/dist/server/api/project-info.d.ts +11 -0
  46. package/packages/core/dist/server/api/project-info.d.ts.map +1 -0
  47. package/packages/core/dist/server/api/project-info.js +18 -0
  48. package/packages/core/dist/server/api/project-info.js.map +1 -0
  49. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  50. package/packages/core/dist/server/otlp-receiver.js +18 -1
  51. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  52. package/packages/core/dist/server/otlp-receiver.test.js +1 -1
  53. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -1
  54. package/packages/core/dist/server/server.d.ts +0 -3
  55. package/packages/core/dist/server/server.d.ts.map +1 -1
  56. package/packages/core/dist/server/server.js +5 -38
  57. package/packages/core/dist/server/server.js.map +1 -1
  58. package/packages/core/dist/server/server.test.d.ts +1 -1
  59. package/packages/core/dist/server/server.test.js +12 -23
  60. package/packages/core/dist/server/server.test.js.map +1 -1
  61. package/packages/core/dist/server/settings.d.ts +1 -0
  62. package/packages/core/dist/server/settings.d.ts.map +1 -1
  63. package/packages/core/dist/server/settings.js +13 -0
  64. package/packages/core/dist/server/settings.js.map +1 -1
  65. package/packages/core/dist/shared/capabilities.d.ts +88 -0
  66. package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
  67. package/packages/core/dist/shared/capabilities.js +133 -0
  68. package/packages/core/dist/shared/capabilities.js.map +1 -0
  69. package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
  70. package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
  71. package/packages/core/dist/shared/capabilities.test.js +217 -0
  72. package/packages/core/dist/shared/capabilities.test.js.map +1 -0
  73. package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
  74. package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
  75. package/packages/core/dist/shared/spawn-prompt.js +82 -0
  76. package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
  77. package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
  78. package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
  79. package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
  80. package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
  81. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
  82. package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
  83. package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
  84. package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
  85. package/packages/core/dist/workflow/team-lifecycle.d.ts +169 -0
  86. package/packages/core/dist/workflow/team-lifecycle.d.ts.map +1 -0
  87. package/packages/core/dist/workflow/team-lifecycle.js +217 -0
  88. package/packages/core/dist/workflow/team-lifecycle.js.map +1 -0
  89. package/packages/core/dist/workflow/team-lifecycle.test.d.ts +20 -0
  90. package/packages/core/dist/workflow/team-lifecycle.test.d.ts.map +1 -0
  91. package/packages/core/dist/workflow/team-lifecycle.test.js +966 -0
  92. package/packages/core/dist/workflow/team-lifecycle.test.js.map +1 -0
  93. package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
  94. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  95. package/packages/core/dist/workflow/workflow-schema.js +120 -0
  96. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  97. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  98. package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
  99. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  100. package/packages/core/dist/workflow/workflow-team-templates.test.d.ts +17 -0
  101. package/packages/core/dist/workflow/workflow-team-templates.test.d.ts.map +1 -0
  102. package/packages/core/dist/workflow/workflow-team-templates.test.js +275 -0
  103. package/packages/core/dist/workflow/workflow-team-templates.test.js.map +1 -0
  104. package/pennyfarthing-dist/agents/dev.md +21 -12
  105. package/pennyfarthing-dist/agents/reviewer.md +23 -4
  106. package/pennyfarthing-dist/agents/sm-finish.md +19 -2
  107. package/pennyfarthing-dist/agents/sm-setup.md +7 -7
  108. package/pennyfarthing-dist/agents/sm.md +12 -12
  109. package/pennyfarthing-dist/agents/tea.md +2 -2
  110. package/pennyfarthing-dist/agents/testing-runner.md +1 -1
  111. package/pennyfarthing-dist/commands/pf-architect.md +1 -1
  112. package/pennyfarthing-dist/commands/pf-ba.md +1 -1
  113. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  114. package/pennyfarthing-dist/commands/pf-dev.md +1 -1
  115. package/pennyfarthing-dist/commands/pf-devops.md +1 -1
  116. package/pennyfarthing-dist/commands/pf-epic.md +6 -6
  117. package/pennyfarthing-dist/commands/pf-git.md +12 -10
  118. package/pennyfarthing-dist/commands/pf-health-check.md +1 -1
  119. package/pennyfarthing-dist/commands/pf-help.md +12 -12
  120. package/pennyfarthing-dist/commands/pf-orchestrator.md +1 -1
  121. package/pennyfarthing-dist/commands/pf-pm.md +1 -1
  122. package/pennyfarthing-dist/commands/pf-prime.md +8 -8
  123. package/pennyfarthing-dist/commands/pf-reviewer.md +1 -1
  124. package/pennyfarthing-dist/commands/pf-session.md +7 -7
  125. package/pennyfarthing-dist/commands/pf-sm.md +1 -1
  126. package/pennyfarthing-dist/commands/pf-sprint.md +7 -7
  127. package/pennyfarthing-dist/commands/pf-tea.md +1 -1
  128. package/pennyfarthing-dist/commands/pf-tech-writer.md +1 -1
  129. package/pennyfarthing-dist/commands/pf-theme.md +9 -9
  130. package/pennyfarthing-dist/commands/pf-ux-designer.md +1 -1
  131. package/pennyfarthing-dist/commands/pf-work.md +1 -1
  132. package/pennyfarthing-dist/gates/approval.md +63 -0
  133. package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
  134. package/pennyfarthing-dist/gates/context-ok.md +56 -0
  135. package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
  136. package/pennyfarthing-dist/gates/quality-pass.md +67 -0
  137. package/pennyfarthing-dist/gates/tests-fail.md +84 -0
  138. package/pennyfarthing-dist/gates/tests-pass.md +79 -0
  139. package/pennyfarthing-dist/guides/agent-behavior.md +84 -29
  140. package/pennyfarthing-dist/guides/agent-coordination.md +10 -10
  141. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +6 -6
  142. package/pennyfarthing-dist/guides/agent-template-tactical.md +1 -1
  143. package/pennyfarthing-dist/guides/bell-mode.md +1 -1
  144. package/pennyfarthing-dist/guides/bikerack.md +10 -10
  145. package/pennyfarthing-dist/guides/brownfield-tools.md +24 -24
  146. package/pennyfarthing-dist/guides/command-tag-taxonomy.md +1 -1
  147. package/pennyfarthing-dist/guides/gate-schema.md +2 -2
  148. package/pennyfarthing-dist/guides/gates.md +3 -3
  149. package/pennyfarthing-dist/guides/handoff-cli.md +8 -8
  150. package/pennyfarthing-dist/guides/hooks.md +29 -29
  151. package/pennyfarthing-dist/guides/prime.md +2 -2
  152. package/pennyfarthing-dist/guides/reflector.md +1 -1
  153. package/pennyfarthing-dist/guides/skill-schema.md +6 -6
  154. package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
  155. package/pennyfarthing-dist/guides/workflow-schema.md +1 -1
  156. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  157. package/pennyfarthing-dist/guides/xml-tags.md +8 -8
  158. package/pennyfarthing-dist/scripts/README.md +4 -4
  159. package/pennyfarthing-dist/scripts/core/agent-session.sh +2 -5
  160. package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
  161. package/pennyfarthing-dist/scripts/core/pf.sh +5 -0
  162. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +4 -89
  163. package/pennyfarthing-dist/scripts/core/prime.sh +2 -25
  164. package/pennyfarthing-dist/scripts/git/README.md +14 -14
  165. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +2 -3
  166. package/pennyfarthing-dist/scripts/git/git-status-all.sh +2 -3
  167. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +2 -3
  168. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +2 -4
  169. package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
  170. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
  171. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
  172. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
  173. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
  174. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +5 -4
  175. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +29 -34
  176. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
  177. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
  178. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
  179. package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
  180. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
  181. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
  182. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +3 -93
  183. package/pennyfarthing-dist/scripts/lib/env.sh +34 -0
  184. package/pennyfarthing-dist/scripts/lib/run-pf.sh +39 -0
  185. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  186. package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
  187. package/pennyfarthing-dist/scripts/sprint/README.md +21 -21
  188. package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
  189. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +2 -16
  190. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +3 -3
  191. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +3 -3
  192. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +3 -3
  193. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +3 -3
  194. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +3 -3
  195. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +3 -3
  196. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +3 -3
  197. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +3 -3
  198. package/pennyfarthing-dist/skills/pf-bc/examples.md +23 -23
  199. package/pennyfarthing-dist/skills/pf-bc/skill.md +17 -17
  200. package/pennyfarthing-dist/skills/pf-bc/usage.md +8 -8
  201. package/pennyfarthing-dist/skills/pf-jira/SKILL.md +15 -15
  202. package/pennyfarthing-dist/skills/pf-jira/examples.md +48 -48
  203. package/pennyfarthing-dist/skills/pf-jira/usage.md +15 -15
  204. package/pennyfarthing-dist/skills/pf-sprint/examples.md +80 -80
  205. package/pennyfarthing-dist/skills/pf-sprint/skill.md +35 -35
  206. package/pennyfarthing-dist/skills/pf-sprint/usage.md +30 -30
  207. package/pennyfarthing-dist/skills/pf-theme/examples.md +15 -15
  208. package/pennyfarthing-dist/skills/pf-theme/skill.md +6 -6
  209. package/pennyfarthing-dist/skills/pf-theme/usage.md +5 -5
  210. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -27
  211. package/pennyfarthing-dist/skills/pf-workflow/skill.md +11 -11
  212. package/pennyfarthing-dist/skills/pf-workflow/usage.md +11 -11
  213. package/pennyfarthing-dist/skills/skill-registry.yaml +19 -19
  214. package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
  215. package/pennyfarthing-dist/workflows/bdd-team.yaml +89 -0
  216. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +1 -1
  217. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
  218. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
  219. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
  220. package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +47 -0
  221. package/pennyfarthing-dist/workflows/tdd-team.yaml +80 -0
  222. package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
  223. package/pennyfarthing_scripts/CLAUDE.md +19 -10
  224. package/pennyfarthing_scripts/__init__.py +1 -1
  225. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  233. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/bc/__pycache__/split.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/bc/cli.py +2 -2
  237. package/pennyfarthing_scripts/bellmode_hook.py +9 -296
  238. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  239. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  240. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  241. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  242. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  243. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  244. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  255. package/pennyfarthing_scripts/bikerack/audit_log_panel.py +161 -0
  256. package/pennyfarthing_scripts/bikerack/base_panel.py +27 -4
  257. package/pennyfarthing_scripts/bikerack/changed_panel.py +96 -4
  258. package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
  259. package/pennyfarthing_scripts/bikerack/debug_panel.py +1 -1
  260. package/pennyfarthing_scripts/bikerack/diffs_panel.py +30 -0
  261. package/pennyfarthing_scripts/bikerack/events.py +28 -0
  262. package/pennyfarthing_scripts/bikerack/launcher.py +6 -6
  263. package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
  264. package/pennyfarthing_scripts/bikerack/progress_panel.py +0 -1
  265. package/pennyfarthing_scripts/bikerack/sprint_panel.py +373 -142
  266. package/pennyfarthing_scripts/bikerack/story_detail_data.py +247 -0
  267. package/pennyfarthing_scripts/bikerack/story_detail_screen.py +177 -0
  268. package/pennyfarthing_scripts/bikerack/tui.py +304 -62
  269. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  270. package/pennyfarthing_scripts/cli.py +5 -0
  271. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/common/config.py +29 -2
  273. package/pennyfarthing_scripts/common/pr_config.py +38 -0
  274. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  276. package/pennyfarthing_scripts/consultation/cli.py +3 -3
  277. package/pennyfarthing_scripts/context.py +3 -3
  278. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  279. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  280. package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/git/hooks_installer.py +2 -3
  283. package/pennyfarthing_scripts/git/status_all.py +1 -1
  284. package/pennyfarthing_scripts/git/worktree.py +2 -2
  285. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  287. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  288. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  289. package/pennyfarthing_scripts/handoff/__pycache__/phase_check.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  291. package/pennyfarthing_scripts/handoff/cli.py +33 -1
  292. package/pennyfarthing_scripts/handoff/complete_phase.py +28 -0
  293. package/pennyfarthing_scripts/handoff/marker.py +15 -15
  294. package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
  295. package/pennyfarthing_scripts/handoff/resolve_gate.py +13 -1
  296. package/pennyfarthing_scripts/hooks/__init__.py +442 -0
  297. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  298. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  302. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  303. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  304. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  305. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  306. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  307. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  308. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  309. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/hooks/bell_mode.py +214 -0
  311. package/pennyfarthing_scripts/hooks/cli.py +96 -0
  312. package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
  313. package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
  314. package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
  315. package/pennyfarthing_scripts/hooks/pre_edit_check.py +77 -0
  316. package/pennyfarthing_scripts/hooks/reflector_check.py +270 -0
  317. package/pennyfarthing_scripts/hooks/schema_validation.py +202 -0
  318. package/pennyfarthing_scripts/hooks/session_start.py +294 -0
  319. package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
  320. package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
  321. package/pennyfarthing_scripts/hooks/statusline.py +429 -0
  322. package/pennyfarthing_scripts/hooks.py +27 -432
  323. package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
  324. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  325. package/pennyfarthing_scripts/prime/heatmap.py +3 -15
  326. package/pennyfarthing_scripts/prime/workflow.py +2 -1
  327. package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
  328. package/pennyfarthing_scripts/session_start_hook.py +4 -186
  329. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  332. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  333. package/pennyfarthing_scripts/sprint/cli.py +121 -0
  334. package/pennyfarthing_scripts/sprint/loader.py +154 -3
  335. package/pennyfarthing_scripts/sprint/story_update.py +26 -0
  336. package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
  337. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  338. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_list_team.cpython-314-pytest-9.0.2.pyc +0 -0
  339. package/pennyfarthing_scripts/tests/test_bikerack.py +26 -26
  340. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +0 -1
  341. package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
  342. package/pennyfarthing_scripts/tests/test_workflow_list_team.py +147 -0
  343. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  344. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  345. package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
  346. package/pennyfarthing_scripts/validate/adapters/__pycache__/team_mode.cpython-314.pyc +0 -0
  347. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  348. package/pennyfarthing_scripts/validate/adapters/team_mode.py +323 -0
  349. package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
  350. package/pennyfarthing_scripts/welcome_hook.py +3 -149
  351. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  352. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  355. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  356. package/pennyfarthing_scripts/workflow/__pycache__/team_lifecycle.cpython-314.pyc +0 -0
  357. package/pennyfarthing_scripts/workflow/cli.py +22 -20
  358. package/pennyfarthing_scripts/workflow/state.py +0 -1
  359. package/pennyfarthing_scripts/workflow/team_lifecycle.py +256 -0
  360. package/packages/core/dist/cli/cyclist-migration.test.d.ts +0 -16
  361. package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +0 -1
  362. package/packages/core/dist/cli/cyclist-migration.test.js +0 -229
  363. package/packages/core/dist/cli/cyclist-migration.test.js.map +0 -1
  364. package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
  365. package/packages/core/dist/scripts/theme-detail.test.d.ts.map +0 -1
  366. package/packages/core/dist/scripts/theme-detail.test.js +0 -199
  367. package/packages/core/dist/scripts/theme-detail.test.js.map +0 -1
@@ -0,0 +1,429 @@
1
+ """
2
+ Claude Code statusline hook — render the status bar.
3
+
4
+ Format: [ROLE] Theme | repo | branch | model [progress] pct%
5
+
6
+ Reads JSON from stdin with workspace, model, session_id, context_window info.
7
+ Outputs ANSI-colored status line to stdout.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import os
14
+ import re
15
+ import subprocess
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ from pennyfarthing_scripts.hooks import load_settings
20
+
21
+ try:
22
+ import yaml
23
+ HAS_YAML = True
24
+ except ImportError:
25
+ HAS_YAML = False
26
+
27
+ # =============================================================================
28
+ # ANSI Colors
29
+ # =============================================================================
30
+
31
+ RESET = "\033[0m"
32
+ DIM = "\033[2m"
33
+ BOLD = "\033[1m"
34
+ REVERSE = "\033[7m"
35
+ FG_CYAN = "\033[36m"
36
+ FG_GREEN = "\033[32m"
37
+ FG_YELLOW = "\033[33m"
38
+ FG_RED = "\033[31m"
39
+ FG_MAGENTA = "\033[35m"
40
+ FG_BLUE = "\033[34m"
41
+ FG_WHITE = "\033[97m"
42
+ FG_GRAY = "\033[38;5;245m"
43
+ FG_ORANGE = "\033[38;5;208m"
44
+ FG_PINK = "\033[38;5;213m"
45
+ FG_TEAL = "\033[38;5;43m"
46
+ FG_PURPLE = "\033[38;5;141m"
47
+ FG_LIME = "\033[38;5;154m"
48
+
49
+ # =============================================================================
50
+ # Agent Maps
51
+ # =============================================================================
52
+
53
+ AGENT_ABBREVS = {
54
+ "pm": "PM",
55
+ "sm": "SM",
56
+ "dev": "DEV",
57
+ "tea": "TEA",
58
+ "reviewer": "REV",
59
+ "architect": "ARC",
60
+ "devops": "OPS",
61
+ "ux-designer": "UX",
62
+ "tech-writer": "DOC",
63
+ "orchestrator": "ORC",
64
+ "ba": "BA",
65
+ }
66
+
67
+ AGENT_COLORS = {
68
+ "pm": f"{FG_PURPLE}{BOLD}",
69
+ "sm": f"{FG_BLUE}{BOLD}",
70
+ "dev": f"{FG_GREEN}{BOLD}",
71
+ "tea": f"{FG_TEAL}{BOLD}",
72
+ "reviewer": f"{FG_RED}{BOLD}",
73
+ "architect": f"{FG_ORANGE}{BOLD}",
74
+ "devops": f"{FG_CYAN}{BOLD}",
75
+ "ux-designer": f"{FG_PINK}{BOLD}",
76
+ "tech-writer": f"{FG_WHITE}{BOLD}",
77
+ "orchestrator": f"{FG_MAGENTA}{BOLD}",
78
+ "ba": f"{FG_LIME}{BOLD}",
79
+ }
80
+
81
+ # Title patterns to strip from character names
82
+ TITLE_PATTERN = re.compile(
83
+ r'^(Captain|Lieutenant|Dr\.|Doc|Mr\.|Mrs\.|Ms\.|Admiral|Commander|'
84
+ r'Chief|Ensign|Translator|Agent|Colonel|Major|Sergeant|Professor|'
85
+ r'Lord|Lady|Sir|The)\s+',
86
+ re.IGNORECASE,
87
+ )
88
+
89
+
90
+ # =============================================================================
91
+ # Helpers
92
+ # =============================================================================
93
+
94
+
95
+ def _get_agent_abbrev(name: str) -> str:
96
+ return AGENT_ABBREVS.get(name, "???")
97
+
98
+
99
+ def _get_agent_color(name: str) -> str:
100
+ return AGENT_COLORS.get(name, f"{FG_MAGENTA}{BOLD}")
101
+
102
+
103
+ def _clean_character_name(full_name: str) -> str:
104
+ """Extract short display name from full character name."""
105
+ # Remove parenthetical: "Breq (Justice of Toren)" → "Breq"
106
+ clean = re.sub(r'\s*\([^)]*\)', '', full_name).strip()
107
+ # Strip titles
108
+ clean = TITLE_PATTERN.sub('', clean).strip()
109
+ words = clean.split()
110
+ if len(words) <= 1:
111
+ return clean
112
+ return words[-1]
113
+
114
+
115
+ def _parse_input() -> dict:
116
+ """Read and parse JSON from stdin."""
117
+ raw = sys.stdin.read()
118
+ try:
119
+ data = json.loads(raw)
120
+ if not isinstance(data, dict):
121
+ return {}
122
+ return data
123
+ except (json.JSONDecodeError, ValueError):
124
+ return {}
125
+
126
+
127
+ def _get_model_name(data: dict) -> str:
128
+ """Extract and clean model name from input."""
129
+ model_raw = data.get("model", "claude")
130
+ if isinstance(model_raw, dict):
131
+ model = model_raw.get("id") or model_raw.get("name") or "claude"
132
+ elif isinstance(model_raw, str):
133
+ model = model_raw
134
+ else:
135
+ model = "claude"
136
+
137
+ if not model or model == "null":
138
+ model = "claude"
139
+
140
+ # Clean: remove "claude-" prefix and trailing version number
141
+ model = re.sub(r'^claude-', '', model)
142
+ model = re.sub(r'-\d+$', '', model)
143
+ return model[:10]
144
+
145
+
146
+ def _get_git_info(cwd: str) -> tuple[str, str]:
147
+ """Get git branch and dirty indicator."""
148
+ branch = ""
149
+ dirty = ""
150
+ try:
151
+ result = subprocess.run(
152
+ ["git", "-C", cwd, "branch", "--show-current"],
153
+ capture_output=True, text=True, timeout=3,
154
+ )
155
+ branch = result.stdout.strip()
156
+ if not branch:
157
+ result = subprocess.run(
158
+ ["git", "-C", cwd, "rev-parse", "--short", "HEAD"],
159
+ capture_output=True, text=True, timeout=3,
160
+ )
161
+ branch = result.stdout.strip()
162
+
163
+ # Check dirty (using diff-index to avoid index.lock issues)
164
+ result = subprocess.run(
165
+ ["git", "-C", cwd, "diff-index", "--quiet", "HEAD", "--"],
166
+ capture_output=True, text=True, timeout=3,
167
+ )
168
+ if result.returncode != 0:
169
+ dirty = "*"
170
+ else:
171
+ # Check for untracked files
172
+ result = subprocess.run(
173
+ ["git", "-C", cwd, "ls-files", "--others", "--exclude-standard"],
174
+ capture_output=True, text=True, timeout=3,
175
+ )
176
+ if result.stdout.strip():
177
+ dirty = "*"
178
+ except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
179
+ pass
180
+
181
+ return branch, dirty
182
+
183
+
184
+ def _get_context_pct(data: dict) -> str | int:
185
+ """Calculate context usage percentage from input data."""
186
+ usage = data.get("context_window", {}).get("current_usage")
187
+ if not usage or not isinstance(usage, dict):
188
+ return "--"
189
+
190
+ current = (
191
+ usage.get("input_tokens", 0) +
192
+ usage.get("cache_creation_input_tokens", 0) +
193
+ usage.get("cache_read_input_tokens", 0)
194
+ )
195
+ size = data.get("context_window", {}).get("context_window_size", 0)
196
+
197
+ if not current or not size or size <= 0:
198
+ return "--"
199
+
200
+ return current * 100 // size
201
+
202
+
203
+ def _resolve_agent(project_root: str, session_id: str) -> str:
204
+ """Resolve agent name from session files."""
205
+ if session_id:
206
+ agent_file = Path(project_root) / ".session" / "agents" / session_id
207
+ if agent_file.is_file():
208
+ try:
209
+ return agent_file.read_text().strip()
210
+ except OSError:
211
+ pass
212
+
213
+ agents_dir = Path(project_root) / ".session" / "agents"
214
+ if agents_dir.is_dir():
215
+ try:
216
+ files = sorted(
217
+ (f for f in agents_dir.iterdir() if f.is_file()),
218
+ key=lambda f: f.stat().st_mtime,
219
+ reverse=True,
220
+ )
221
+ if files:
222
+ return files[0].read_text().strip()
223
+ except OSError:
224
+ pass
225
+
226
+ return ""
227
+
228
+
229
+ def _get_character_display(project_root: str, agent_name: str) -> tuple[str, str | None]:
230
+ """Get character display name and theme file path.
231
+
232
+ Returns:
233
+ Tuple of (character_display, theme_file_path)
234
+ """
235
+ if not HAS_YAML or not agent_name:
236
+ return "", None
237
+
238
+ config_file = None
239
+ for name in ("config.local.yaml", "persona-config.yaml"):
240
+ candidate = Path(project_root) / ".pennyfarthing" / name
241
+ if candidate.is_file():
242
+ config_file = candidate
243
+ break
244
+
245
+ if not config_file:
246
+ return "", None
247
+
248
+ try:
249
+ with open(config_file) as f:
250
+ config = yaml.safe_load(f) or {}
251
+ except (OSError, yaml.YAMLError):
252
+ return "", None
253
+
254
+ theme = config.get("theme")
255
+ if not theme:
256
+ return "", None
257
+
258
+ theme_file = Path(project_root) / ".pennyfarthing" / "personas" / "themes" / f"{theme}.yaml"
259
+ if not theme_file.is_file():
260
+ # Capitalize theme name as fallback
261
+ return theme[0].upper() + theme[1:] if theme else "", str(theme_file)
262
+
263
+ try:
264
+ with open(theme_file) as f:
265
+ theme_data = yaml.safe_load(f) or {}
266
+ except (OSError, yaml.YAMLError):
267
+ return theme[0].upper() + theme[1:] if theme else "", str(theme_file)
268
+
269
+ full_name = (theme_data.get("agents", {}).get(agent_name, {}) or {}).get("character")
270
+ if full_name:
271
+ return _clean_character_name(full_name), str(theme_file)
272
+
273
+ return theme[0].upper() + theme[1:] if theme else "", str(theme_file)
274
+
275
+
276
+ def _get_tandem_partner_display(project_root: str, theme_file: str | None) -> str:
277
+ """Find active tandem partner and return display name."""
278
+ session_dir = Path(project_root) / ".session"
279
+ if not session_dir.is_dir():
280
+ return ""
281
+
282
+ tandem_files = list(session_dir.glob("*-tandem-*.md"))
283
+ if not tandem_files:
284
+ return ""
285
+
286
+ tandem_file = tandem_files[0]
287
+ match = re.search(r'-tandem-([a-zA-Z_-]+)\.md$', tandem_file.name)
288
+ if not match:
289
+ return ""
290
+
291
+ partner_name = match.group(1)
292
+
293
+ if HAS_YAML and theme_file and Path(theme_file).is_file():
294
+ try:
295
+ with open(theme_file) as f:
296
+ theme_data = yaml.safe_load(f) or {}
297
+ full_name = (theme_data.get("agents", {}).get(partner_name, {}) or {}).get("character")
298
+ if full_name:
299
+ return _clean_character_name(full_name)
300
+ except (OSError, yaml.YAMLError):
301
+ pass
302
+
303
+ return _get_agent_abbrev(partner_name)
304
+
305
+
306
+ def _build_progress_bar(pct: str | int) -> tuple[str, str]:
307
+ """Build progress bar and pct display with ANSI colors.
308
+
309
+ Returns:
310
+ Tuple of (progress_bar, pct_display)
311
+ """
312
+ bar_width = 10
313
+
314
+ if pct == "--" or not isinstance(pct, int):
315
+ bar = f"{DIM}{'░' * bar_width}{RESET}"
316
+ pct_str = f"{FG_GRAY}--%{RESET}"
317
+ return bar, pct_str
318
+
319
+ filled = max(0, min(bar_width, pct * bar_width // 100))
320
+
321
+ if pct > 95:
322
+ color = f"{FG_RED}{BOLD}"
323
+ elif pct > 85:
324
+ color = FG_RED
325
+ elif pct > 70:
326
+ color = FG_YELLOW
327
+ else:
328
+ color = FG_GREEN
329
+
330
+ bar = f"{color}{'▓' * filled}{RESET}{DIM}{'░' * (bar_width - filled)}{RESET}"
331
+ pct_str = f"{color}{pct}%{RESET}"
332
+ return bar, pct_str
333
+
334
+
335
+ # =============================================================================
336
+ # Entry Point
337
+ # =============================================================================
338
+
339
+
340
+ def main() -> None:
341
+ """Main entry point for statusline hook."""
342
+ try:
343
+ data = _parse_input()
344
+ if not data:
345
+ print("⚠ invalid input", end="")
346
+ sys.exit(0)
347
+
348
+ cwd = data.get("workspace", {}).get("current_dir", "")
349
+ dir_name = Path(cwd).name if cwd else "?"
350
+ project_root = os.environ.get("CLAUDE_PROJECT_DIR", cwd)
351
+ session_id = data.get("session_id", "")
352
+
353
+ model = _get_model_name(data)
354
+
355
+ # Check git_monitor setting — skip git calls when disabled
356
+ _settings = load_settings(Path(project_root) if project_root else None)
357
+ if cwd and _settings.git_monitor:
358
+ branch, branch_dirty = _get_git_info(cwd)
359
+ else:
360
+ branch, branch_dirty = "", ""
361
+
362
+ pct = _get_context_pct(data)
363
+
364
+ agent_name = _resolve_agent(project_root, session_id)
365
+ agent_abbrev = _get_agent_abbrev(agent_name) if agent_name else ""
366
+ theme_display, theme_file = _get_character_display(project_root, agent_name)
367
+ tandem_display = _get_tandem_partner_display(project_root, theme_file)
368
+
369
+ # Build progress bar
370
+ progress_bar, pct_display = _build_progress_bar(pct)
371
+
372
+ # Branch color
373
+ branch_color = FG_YELLOW if branch_dirty else FG_GREEN
374
+
375
+ # Fixed-width formatting
376
+ repo_fmt = f"{dir_name:<14}"
377
+ branch_fmt = f"{branch}{branch_dirty}"[:12]
378
+ branch_fmt = f"{branch_fmt:<12}"
379
+ model_fmt = f"{model:<10}"
380
+
381
+ # Tandem suffix
382
+ tandem_suffix = ""
383
+ tandem_suffix_len = 0
384
+ if tandem_display:
385
+ partner_color = _get_agent_color(tandem_display) if tandem_display in AGENT_ABBREVS else _get_agent_color("")
386
+ tandem_suffix = f" {DIM}+{RESET} {partner_color}{tandem_display}{RESET}"
387
+ tandem_suffix_len = 3 + len(tandem_display)
388
+
389
+ # Agent section
390
+ if agent_abbrev:
391
+ agent_color = _get_agent_color(agent_name)
392
+ if theme_display:
393
+ agent_section = f"{agent_color}{REVERSE} {agent_abbrev} {RESET} {DIM}{theme_display}{RESET}{tandem_suffix}"
394
+ pad_len = max(0, 18 - len(agent_abbrev) - len(theme_display) - tandem_suffix_len)
395
+ agent_section += " " * pad_len
396
+ else:
397
+ agent_section = f"{agent_color}{REVERSE} {agent_abbrev} {RESET}{tandem_suffix}"
398
+ pad_len = max(0, 17 - len(agent_abbrev) - tandem_suffix_len)
399
+ agent_section += " " * pad_len
400
+ elif theme_display:
401
+ agent_section = f"{DIM}{theme_display}{RESET}{tandem_suffix}"
402
+ pad_len = max(0, 20 - len(theme_display) - tandem_suffix_len)
403
+ agent_section += " " * pad_len
404
+ else:
405
+ agent_section = " " * 20
406
+
407
+ # Build output
408
+ output = (
409
+ f"{agent_section}"
410
+ f"{DIM}│{RESET} "
411
+ f"{FG_CYAN}{repo_fmt}{RESET}"
412
+ f"{DIM}│{RESET} "
413
+ f"{branch_color}{branch_fmt}{RESET}"
414
+ f"{DIM}│{RESET} "
415
+ f"{FG_GRAY}{model_fmt}{RESET}"
416
+ f"{progress_bar} "
417
+ f"{pct_display}"
418
+ )
419
+
420
+ print(output, end="")
421
+
422
+ except Exception:
423
+ print("⚠ error", end="")
424
+
425
+ sys.exit(0)
426
+
427
+
428
+ if __name__ == "__main__":
429
+ main()