@pennyfarthing/core 11.1.0 → 11.2.0

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 (263) hide show
  1. package/README.md +8 -8
  2. package/package.json +16 -14
  3. package/packages/core/dist/cli/utils/constants.d.ts +1 -1
  4. package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
  5. package/packages/core/dist/cli/utils/constants.js +2 -1
  6. package/packages/core/dist/cli/utils/constants.js.map +1 -1
  7. package/packages/core/dist/consultation/dialogue-manager.d.ts +75 -0
  8. package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -0
  9. package/packages/core/dist/consultation/dialogue-manager.js +334 -0
  10. package/packages/core/dist/consultation/dialogue-manager.js.map +1 -0
  11. package/packages/core/dist/consultation/dialogue-manager.test.d.ts +19 -0
  12. package/packages/core/dist/consultation/dialogue-manager.test.d.ts.map +1 -0
  13. package/packages/core/dist/consultation/dialogue-manager.test.js +444 -0
  14. package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -0
  15. package/packages/core/dist/server/api/git.d.ts +13 -1
  16. package/packages/core/dist/server/api/git.d.ts.map +1 -1
  17. package/packages/core/dist/server/api/git.js +53 -34
  18. package/packages/core/dist/server/api/git.js.map +1 -1
  19. package/packages/core/dist/server/otlp-receiver.d.ts +16 -11
  20. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  21. package/packages/core/dist/server/otlp-receiver.js +185 -24
  22. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  23. package/packages/core/dist/server/otlp-receiver.test.d.ts +21 -0
  24. package/packages/core/dist/server/otlp-receiver.test.d.ts.map +1 -0
  25. package/packages/core/dist/server/otlp-receiver.test.js +446 -0
  26. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -0
  27. package/packages/core/dist/shared/portrait-resolver.d.ts +9 -0
  28. package/packages/core/dist/shared/portrait-resolver.d.ts.map +1 -1
  29. package/packages/core/dist/shared/portrait-resolver.js +27 -0
  30. package/packages/core/dist/shared/portrait-resolver.js.map +1 -1
  31. package/packages/core/dist/shared/portrait-resolver.test.js +47 -1
  32. package/packages/core/dist/shared/portrait-resolver.test.js.map +1 -1
  33. package/packages/core/dist/shared/skill-search.test.js +2 -2
  34. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts +13 -0
  35. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts.map +1 -0
  36. package/packages/core/dist/shared/tandem-portrait-inventory.test.js +126 -0
  37. package/packages/core/dist/shared/tandem-portrait-inventory.test.js.map +1 -0
  38. package/pennyfarthing-dist/agents/dev.md +1 -1
  39. package/pennyfarthing-dist/agents/reviewer.md +1 -1
  40. package/pennyfarthing-dist/agents/sm-setup.md +1 -1
  41. package/pennyfarthing-dist/agents/sm.md +2 -2
  42. package/pennyfarthing-dist/agents/tea.md +1 -1
  43. package/pennyfarthing-dist/agents/testing-runner.md +2 -1
  44. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  45. package/pennyfarthing-dist/commands/pf-standalone.md +7 -2
  46. package/pennyfarthing-dist/guides/agent-behavior.md +1 -1
  47. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +1 -1
  48. package/pennyfarthing-dist/guides/bikerack.md +3 -3
  49. package/pennyfarthing-dist/guides/hooks.md +1 -1
  50. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  51. package/pennyfarthing-dist/guides/xml-tags.md +2 -2
  52. package/pennyfarthing-dist/scripts/README.md +1 -1
  53. package/pennyfarthing-dist/scripts/core/agent-session.sh +0 -0
  54. package/pennyfarthing-dist/scripts/core/check-context.sh +1 -1
  55. package/pennyfarthing-dist/scripts/core/dialogue-manager.sh +322 -0
  56. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +0 -0
  57. package/pennyfarthing-dist/scripts/core/prime.sh +0 -0
  58. package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +0 -0
  59. package/pennyfarthing-dist/scripts/git/README.md +24 -14
  60. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +5 -266
  61. package/pennyfarthing-dist/scripts/git/git-status-all.sh +5 -151
  62. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +6 -144
  63. package/pennyfarthing-dist/scripts/git/release.sh +0 -0
  64. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +5 -496
  65. package/pennyfarthing-dist/scripts/health/drift-detection.sh +0 -0
  66. package/pennyfarthing-dist/scripts/hooks/README.md +1 -1
  67. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +1 -1
  68. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +0 -0
  69. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +0 -0
  70. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +0 -0
  71. package/pennyfarthing-dist/scripts/hooks/dispatcher-template.sh +0 -0
  72. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +9 -11
  73. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +0 -0
  74. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +0 -0
  75. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +0 -0
  76. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +0 -0
  77. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +0 -0
  78. package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +0 -0
  79. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +0 -0
  80. package/pennyfarthing-dist/scripts/hooks/session-start.sh +0 -0
  81. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +0 -0
  82. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +0 -0
  83. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +1 -1
  84. package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +0 -0
  85. package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +0 -0
  86. package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +0 -0
  87. package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +0 -0
  88. package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +0 -0
  89. package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +0 -0
  90. package/pennyfarthing-dist/scripts/lib/background-tasks.sh +0 -0
  91. package/pennyfarthing-dist/scripts/lib/checkpoint.sh +0 -0
  92. package/pennyfarthing-dist/scripts/lib/common.sh +0 -0
  93. package/pennyfarthing-dist/scripts/lib/file-lock.sh +0 -0
  94. package/pennyfarthing-dist/scripts/lib/logging.sh +0 -0
  95. package/pennyfarthing-dist/scripts/lib/retry.sh +0 -0
  96. package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +0 -0
  97. package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +0 -0
  98. package/pennyfarthing-dist/scripts/misc/add-short-names.sh +0 -0
  99. package/pennyfarthing-dist/scripts/misc/add_short_names.py +0 -0
  100. package/pennyfarthing-dist/scripts/misc/backlog.sh +0 -0
  101. package/pennyfarthing-dist/scripts/misc/check-status.sh +0 -0
  102. package/pennyfarthing-dist/scripts/misc/find-related-work.sh +0 -0
  103. package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +0 -0
  104. package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +0 -0
  105. package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +0 -0
  106. package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +0 -0
  107. package/pennyfarthing-dist/scripts/misc/repo-scan.sh +0 -0
  108. package/pennyfarthing-dist/scripts/misc/repo-utils.sh +0 -0
  109. package/pennyfarthing-dist/scripts/misc/run-ci.sh +0 -0
  110. package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +0 -0
  111. package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +0 -0
  112. package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +0 -0
  113. package/pennyfarthing-dist/scripts/misc/statusline.sh +0 -0
  114. package/pennyfarthing-dist/scripts/misc/uninstall.sh +0 -0
  115. package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +0 -0
  116. package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +0 -0
  117. package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +76 -0
  118. package/pennyfarthing-dist/scripts/story/create-story.sh +0 -0
  119. package/pennyfarthing-dist/scripts/story/size-story.sh +0 -0
  120. package/pennyfarthing-dist/scripts/story/story-template.sh +0 -0
  121. package/pennyfarthing-dist/scripts/tests/check.test.sh +0 -0
  122. package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +0 -0
  123. package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +0 -0
  124. package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +0 -0
  125. package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +0 -0
  126. package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +0 -0
  127. package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +0 -0
  128. package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +0 -0
  129. package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +0 -0
  130. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +0 -0
  131. package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +0 -0
  132. package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +0 -0
  133. package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +0 -0
  134. package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +0 -0
  135. package/pennyfarthing-dist/scripts/theme/list-themes.sh +0 -0
  136. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +0 -0
  137. package/pennyfarthing-dist/scripts/workflow/check.py +0 -0
  138. package/pennyfarthing-dist/scripts/workflow/check.sh +0 -0
  139. package/pennyfarthing-dist/scripts/workflow/complete-step.py +0 -0
  140. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +0 -0
  141. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +4 -221
  142. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +0 -0
  143. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +5 -13
  144. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +4 -123
  145. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +4 -33
  146. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +4 -156
  147. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +4 -131
  148. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +4 -249
  149. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +4 -160
  150. package/pennyfarthing-dist/skills/pf-bc/usage.md +1 -1
  151. package/pennyfarthing-dist/skills/pf-jira/examples.md +5 -2
  152. package/pennyfarthing-dist/skills/pf-story/scripts/create-story.sh +0 -0
  153. package/pennyfarthing-dist/skills/pf-story/scripts/size-story.sh +0 -0
  154. package/pennyfarthing-dist/skills/pf-story/scripts/story-template.sh +0 -0
  155. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -16
  156. package/pennyfarthing-dist/skills/pf-workflow/skill.md +9 -12
  157. package/pennyfarthing-dist/skills/pf-workflow/usage.md +33 -8
  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_scripts/CLAUDE.md +26 -4
  165. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  166. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  167. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  168. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  169. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  170. package/pennyfarthing_scripts/bc/cli.py +3 -5
  171. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  172. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  173. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  174. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  179. package/pennyfarthing_scripts/bikerack/__pycache__/portrait.cpython-314.pyc +0 -0
  180. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  181. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  182. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  183. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  184. package/pennyfarthing_scripts/bikerack/background_panel.py +86 -5
  185. package/pennyfarthing_scripts/bikerack/base_panel.py +62 -0
  186. package/pennyfarthing_scripts/bikerack/changed_panel.py +32 -28
  187. package/pennyfarthing_scripts/bikerack/cli.py +10 -11
  188. package/pennyfarthing_scripts/bikerack/debug_panel.py +31 -1
  189. package/pennyfarthing_scripts/bikerack/diffs_panel.py +74 -17
  190. package/pennyfarthing_scripts/bikerack/git_panel.py +103 -33
  191. package/pennyfarthing_scripts/bikerack/launcher.py +15 -15
  192. package/pennyfarthing_scripts/bikerack/progress_panel.py +315 -0
  193. package/pennyfarthing_scripts/bikerack/sprint_panel.py +158 -26
  194. package/pennyfarthing_scripts/bikerack/tui.py +336 -30
  195. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  196. package/pennyfarthing_scripts/cli.py +37 -65
  197. package/pennyfarthing_scripts/consultation/__init__.py +1 -0
  198. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/consultation/cli.py +149 -0
  201. package/pennyfarthing_scripts/consultation/dialogue_manager.py +417 -0
  202. package/pennyfarthing_scripts/context.py +3 -3
  203. package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/git/__init__.py +12 -1
  206. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/git/__pycache__/hooks_installer.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  211. package/pennyfarthing_scripts/git/__pycache__/worktree.cpython-314.pyc +0 -0
  212. package/pennyfarthing_scripts/git/create_branches.py +3 -4
  213. package/pennyfarthing_scripts/git/hooks_installer.py +152 -0
  214. package/pennyfarthing_scripts/git/repos.py +196 -0
  215. package/pennyfarthing_scripts/git/status_all.py +27 -11
  216. package/pennyfarthing_scripts/git/worktree.py +302 -0
  217. package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
  218. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  219. package/pennyfarthing_scripts/git_group/cli.py +143 -40
  220. package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
  221. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  222. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  223. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/handoff/complete_phase.py +12 -0
  225. package/pennyfarthing_scripts/handoff/resolve_gate.py +5 -14
  226. package/pennyfarthing_scripts/hooks/cyclist-pretooluse-hook.sh +0 -0
  227. package/pennyfarthing_scripts/hooks.py +3 -17
  228. package/pennyfarthing_scripts/pretooluse_hook.py +1 -1
  229. package/pennyfarthing_scripts/prime/__pycache__/heatmap.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/prime/heatmap.py +655 -0
  232. package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
  233. package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/session_start_hook.py +1 -1
  235. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/sprint/loader.py +15 -1
  237. package/pennyfarthing_scripts/sprint/story_finish.py +14 -0
  238. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  239. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
  240. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  241. package/pennyfarthing_scripts/tests/test_bikerack.py +51 -51
  242. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +811 -0
  243. package/pennyfarthing_scripts/tests/test_handoff_cli.py +16 -11
  244. package/pennyfarthing_scripts/tests/test_workflow_check.py +2 -3
  245. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/validate/adapters/tandem_awareness.py +254 -0
  247. package/pennyfarthing_scripts/validate/cli.py +17 -5
  248. package/pennyfarthing_scripts/workflow/__init__.py +40 -0
  249. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/workflow/cli.py +1099 -0
  255. package/pennyfarthing_scripts/workflow/helpers.py +241 -0
  256. package/pennyfarthing_scripts/{workflow.py → workflow/scale.py} +0 -104
  257. package/pennyfarthing_scripts/workflow/state.py +112 -0
  258. package/scripts/README.md +41 -0
  259. package/pennyfarthing-dist/skills/pf-workflow/scripts/list-workflows.sh +0 -91
  260. package/pennyfarthing-dist/skills/pf-workflow/scripts/resume-workflow.sh +0 -163
  261. package/pennyfarthing-dist/skills/pf-workflow/scripts/show-workflow.sh +0 -138
  262. package/pennyfarthing-dist/skills/pf-workflow/scripts/start-workflow.sh +0 -273
  263. package/pennyfarthing-dist/skills/pf-workflow/scripts/workflow-status.sh +0 -167
@@ -0,0 +1,322 @@
1
+ #!/usr/bin/env bash
2
+ # dialogue-manager.sh — Dialogue file management for tandem agent consultation
3
+ #
4
+ # Creates, appends to, and archives dialogue files recording consultation exchanges
5
+ # between tandem agents. Format defined in ADR-0012 (lines 156-195).
6
+ #
7
+ # Usage:
8
+ # dialogue-manager.sh init <story-id> <workflow> <leader> <partner>
9
+ # dialogue-manager.sh append <story-id> <question> <recommendation> <confidence>
10
+ # dialogue-manager.sh outcome <story-id> <exchange-num> <applied|deferred|rejected> [note]
11
+ # dialogue-manager.sh summarize <story-id>
12
+ # dialogue-manager.sh archive <story-id> [jira-key]
13
+
14
+ set -euo pipefail
15
+
16
+ # Self-locate and set up PROJECT_ROOT
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
18
+ source "$SCRIPT_DIR/../lib/find-root.sh"
19
+
20
+ SESSION_DIR="$PROJECT_ROOT/.session"
21
+ ARCHIVE_DIR="$PROJECT_ROOT/sprint/archive"
22
+ SUMMARY_MARKER="## Summary"
23
+
24
+ # =============================================================================
25
+ # Helpers
26
+ # =============================================================================
27
+
28
+ usage() {
29
+ echo "Usage:"
30
+ echo " dialogue-manager.sh init <story-id> <workflow> <leader> <partner>"
31
+ echo " dialogue-manager.sh append <story-id> <question> <recommendation> <confidence>"
32
+ echo " dialogue-manager.sh outcome <story-id> <exchange-num> <applied|deferred|rejected> [note]"
33
+ echo " dialogue-manager.sh summarize <story-id>"
34
+ echo " dialogue-manager.sh archive <story-id> [jira-key]"
35
+ exit 1
36
+ }
37
+
38
+ dialogue_path() {
39
+ echo "$SESSION_DIR/${1}-dialogue.md"
40
+ }
41
+
42
+ now_iso() {
43
+ date -u +"%Y-%m-%dT%H:%M:%SZ"
44
+ }
45
+
46
+ now_hhmm() {
47
+ date -u +"%H:%M"
48
+ }
49
+
50
+ # Count existing exchanges in a dialogue file
51
+ count_exchanges() {
52
+ local file="$1"
53
+ grep -c '^## Exchange ' "$file" 2>/dev/null || echo "0"
54
+ }
55
+
56
+ # =============================================================================
57
+ # Commands
58
+ # =============================================================================
59
+
60
+ cmd_init() {
61
+ local story_id="${1:?Missing story-id}"
62
+ local workflow="${2:?Missing workflow}"
63
+ local leader="${3:?Missing leader}"
64
+ local partner="${4:?Missing partner}"
65
+ local file
66
+ file="$(dialogue_path "$story_id")"
67
+
68
+ if [[ -f "$file" ]]; then
69
+ echo "Dialogue file already exists: $file"
70
+ exit 0
71
+ fi
72
+
73
+ mkdir -p "$SESSION_DIR"
74
+
75
+ cat > "$file" <<EOF
76
+ # Tandem Dialogue: ${story_id}
77
+
78
+ **Workflow:** ${workflow}
79
+ **Leader:** ${leader} | **Partner:** ${partner}
80
+ **Started:** $(now_iso)
81
+
82
+ ---
83
+
84
+ ${SUMMARY_MARKER}
85
+ - **Total exchanges:** 0
86
+ - **Key decisions:** None
87
+ - **Time in tandem:** 0m
88
+ EOF
89
+
90
+ echo "Created dialogue file: $file"
91
+ }
92
+
93
+ cmd_append() {
94
+ local story_id="${1:?Missing story-id}"
95
+ local question="${2:?Missing question}"
96
+ local recommendation="${3:?Missing recommendation}"
97
+ local confidence="${4:?Missing confidence}"
98
+ local file
99
+ file="$(dialogue_path "$story_id")"
100
+
101
+ # Auto-init if file missing
102
+ if [[ ! -f "$file" ]]; then
103
+ echo "Error: Dialogue file not found. Run 'init' first: $file" >&2
104
+ exit 1
105
+ fi
106
+
107
+ local num
108
+ num=$(( $(count_exchanges "$file") + 1 ))
109
+ local ts
110
+ ts="$(now_hhmm)"
111
+
112
+ # Extract leader and partner from header
113
+ local leader partner
114
+ leader=$(grep '^\*\*Leader:\*\*' "$file" | sed 's/.*\*\*Leader:\*\* \([^ ]*\).*/\1/' | head -1)
115
+ partner=$(grep '^\*\*Leader:\*\*' "$file" | sed 's/.*\*\*Partner:\*\* \([^ ]*\).*/\1/' | head -1)
116
+
117
+ # Fallback if parsing fails
118
+ leader="${leader:-leader}"
119
+ partner="${partner:-partner}"
120
+
121
+ local exchange_block
122
+ exchange_block="## Exchange ${num}
123
+ **[${ts}] ${leader} → ${partner}**
124
+
125
+ > ${question}
126
+
127
+ **[${ts}] ${partner}:**
128
+
129
+ ${recommendation}
130
+
131
+ **Confidence:** ${confidence}
132
+
133
+ **Outcome:** _pending_
134
+
135
+ ---
136
+ "
137
+
138
+ # Insert before summary marker
139
+ if grep -q "^${SUMMARY_MARKER}" "$file"; then
140
+ # Use awk to insert before summary
141
+ local tmpfile
142
+ tmpfile="$(mktemp)"
143
+ awk -v block="$exchange_block" -v marker="$SUMMARY_MARKER" '
144
+ $0 == marker { printf "%s\n\n", block }
145
+ { print }
146
+ ' "$file" > "$tmpfile"
147
+ mv "$tmpfile" "$file"
148
+ else
149
+ echo "" >> "$file"
150
+ echo "$exchange_block" >> "$file"
151
+ fi
152
+
153
+ echo "Appended exchange #${num} to $file"
154
+ }
155
+
156
+ cmd_outcome() {
157
+ local story_id="${1:?Missing story-id}"
158
+ local exchange_num="${2:?Missing exchange-num}"
159
+ local outcome="${3:?Missing outcome (applied|deferred|rejected)}"
160
+ local note="${4:-}"
161
+ local file
162
+ file="$(dialogue_path "$story_id")"
163
+
164
+ if [[ ! -f "$file" ]]; then
165
+ echo "Error: Dialogue file not found: $file" >&2
166
+ exit 1
167
+ fi
168
+
169
+ # Validate outcome
170
+ case "$outcome" in
171
+ applied|deferred|rejected) ;;
172
+ *) echo "Error: outcome must be applied, deferred, or rejected" >&2; exit 1 ;;
173
+ esac
174
+
175
+ local outcome_text
176
+ if [[ -n "$note" ]]; then
177
+ outcome_text="**Outcome:** ${outcome} - ${note}"
178
+ else
179
+ outcome_text="**Outcome:** ${outcome}"
180
+ fi
181
+
182
+ # Find the exchange and update its outcome line
183
+ local in_target=false
184
+ local found=false
185
+ local tmpfile
186
+ tmpfile="$(mktemp)"
187
+
188
+ while IFS= read -r line; do
189
+ if [[ "$line" =~ ^##\ Exchange\ ([0-9]+) ]]; then
190
+ if [[ "${BASH_REMATCH[1]}" == "$exchange_num" ]]; then
191
+ in_target=true
192
+ else
193
+ in_target=false
194
+ fi
195
+ fi
196
+
197
+ if $in_target && [[ "$line" =~ ^\*\*Outcome:\*\* ]]; then
198
+ echo "$outcome_text" >> "$tmpfile"
199
+ found=true
200
+ in_target=false
201
+ else
202
+ echo "$line" >> "$tmpfile"
203
+ fi
204
+ done < "$file"
205
+
206
+ if $found; then
207
+ mv "$tmpfile" "$file"
208
+ echo "Updated exchange #${exchange_num} outcome to: ${outcome}"
209
+ else
210
+ rm -f "$tmpfile"
211
+ echo "Error: Exchange #${exchange_num} not found" >&2
212
+ exit 1
213
+ fi
214
+ }
215
+
216
+ cmd_summarize() {
217
+ local story_id="${1:?Missing story-id}"
218
+ local file
219
+ file="$(dialogue_path "$story_id")"
220
+
221
+ if [[ ! -f "$file" ]]; then
222
+ echo "Error: Dialogue file not found: $file" >&2
223
+ exit 1
224
+ fi
225
+
226
+ local total
227
+ total="$(count_exchanges "$file")"
228
+
229
+ # Collect applied decisions
230
+ local decisions=""
231
+ local in_exchange=false
232
+ local current_outcome=""
233
+ local current_note=""
234
+
235
+ while IFS= read -r line; do
236
+ if [[ "$line" =~ ^\*\*Outcome:\*\*\ applied ]]; then
237
+ local note_part="${line#*applied}"
238
+ note_part="${note_part# - }"
239
+ if [[ -n "$note_part" ]]; then
240
+ decisions="${decisions} - ${note_part}\n"
241
+ fi
242
+ fi
243
+ done < "$file"
244
+
245
+ if [[ -z "$decisions" ]]; then
246
+ decisions="None"
247
+ fi
248
+
249
+ # Calculate time span from first and last exchange timestamps
250
+ local first_ts last_ts duration="0m"
251
+ first_ts=$(grep -m 1 '^\*\*\[' "$file" | sed 's/.*\*\*\[\([0-9]*:[0-9]*\)\].*/\1/' || echo "")
252
+ last_ts=$(grep '^\*\*\[' "$file" | tail -1 | sed 's/.*\*\*\[\([0-9]*:[0-9]*\)\].*/\1/' || echo "")
253
+
254
+ if [[ -n "$first_ts" && -n "$last_ts" ]]; then
255
+ local first_mins last_mins
256
+ first_mins=$(( 10#${first_ts%%:*} * 60 + 10#${first_ts##*:} ))
257
+ last_mins=$(( 10#${last_ts%%:*} * 60 + 10#${last_ts##*:} ))
258
+ local diff=$(( last_mins - first_mins ))
259
+ if (( diff > 0 )); then
260
+ duration="${diff}m"
261
+ fi
262
+ fi
263
+
264
+ # Build new summary
265
+ local new_summary="${SUMMARY_MARKER}
266
+ - **Total exchanges:** ${total}
267
+ - **Key decisions:**
268
+ $(echo -e "$decisions")- **Time in tandem:** ${duration}"
269
+
270
+ # Replace summary section (everything from marker to end)
271
+ if grep -q "^${SUMMARY_MARKER}" "$file"; then
272
+ local tmpfile
273
+ tmpfile="$(mktemp)"
274
+ awk -v marker="$SUMMARY_MARKER" '
275
+ $0 == marker { found=1; next }
276
+ !found { print }
277
+ ' "$file" > "$tmpfile"
278
+ echo "$new_summary" >> "$tmpfile"
279
+ mv "$tmpfile" "$file"
280
+ else
281
+ echo "" >> "$file"
282
+ echo "$new_summary" >> "$file"
283
+ fi
284
+
285
+ echo "Summary refreshed for $file (${total} exchanges)"
286
+ }
287
+
288
+ cmd_archive() {
289
+ local story_id="${1:?Missing story-id}"
290
+ local jira_key="${2:-}"
291
+ local file
292
+ file="$(dialogue_path "$story_id")"
293
+
294
+ if [[ ! -f "$file" ]]; then
295
+ echo "No dialogue file to archive: $file"
296
+ exit 0
297
+ fi
298
+
299
+ mkdir -p "$ARCHIVE_DIR"
300
+
301
+ local prefix="${jira_key:-$story_id}"
302
+ local dest="$ARCHIVE_DIR/${prefix}-dialogue.md"
303
+
304
+ cp "$file" "$dest"
305
+ echo "Archived dialogue to: $dest"
306
+ }
307
+
308
+ # =============================================================================
309
+ # Dispatch
310
+ # =============================================================================
311
+
312
+ CMD="${1:-}"
313
+ shift || true
314
+
315
+ case "$CMD" in
316
+ init) cmd_init "$@" ;;
317
+ append) cmd_append "$@" ;;
318
+ outcome) cmd_outcome "$@" ;;
319
+ summarize) cmd_summarize "$@" ;;
320
+ archive) cmd_archive "$@" ;;
321
+ *) usage ;;
322
+ esac
File without changes
File without changes
@@ -1,23 +1,33 @@
1
1
  # Git Scripts
2
2
 
3
- Scripts for Git operations, branching, and release management.
3
+ Scripts for Git operations, branching, and worktree management.
4
4
 
5
- ## Scripts
5
+ ## CLI Commands (preferred)
6
6
 
7
- | Script | Purpose |
8
- |--------|---------|
9
- | `create-feature-branches.sh` | Create feature branches in repos |
10
- | `git-status-all.sh` | Show git status across all repos |
11
- | `worktree-manager.sh` | Manage git worktrees for parallel work |
12
- | `install-git-hooks.sh` | Install git hooks in project |
13
- | `release.sh` | Release workflow (merge develop to main) |
7
+ All git operations are available via the `pf git` CLI:
14
8
 
15
- ## Usage
9
+ | Command | Purpose |
10
+ |---------|---------|
11
+ | `pf git status [--brief]` | Show git status across all repos |
12
+ | `pf git branches <name> [--repos all\|api\|ui]` | Create feature branches in repos |
13
+ | `pf git worktree create <name> <branch>` | Create worktrees for parallel work |
14
+ | `pf git worktree remove <name>` | Remove worktree and clean up |
15
+ | `pf git worktree list` | List all active worktrees |
16
+ | `pf git worktree status` | Show detailed worktree status |
17
+ | `pf git install-hooks` | Install git hooks with .d/ dispatcher |
18
+ | `pf git cleanup` | Organize changes into commits/branches |
16
19
 
17
- ```bash
18
- .pennyfarthing/scripts/git/create-feature-branches.sh feat/my-feature
19
- .pennyfarthing/scripts/git/release.sh
20
- ```
20
+ ## Legacy Scripts (deprecated shims)
21
+
22
+ These scripts now forward to `pf git` commands:
23
+
24
+ | Script | Forwards to |
25
+ |--------|-------------|
26
+ | `git-status-all.sh` | `pf git status` |
27
+ | `create-feature-branches.sh` | `pf git branches` |
28
+ | `worktree-manager.sh` | `pf git worktree` |
29
+ | `install-git-hooks.sh` | `pf git install-hooks` |
30
+ | `release.sh` | Release workflow (use `/pf-workflow start release`) |
21
31
 
22
32
  ## Ownership
23
33
 
@@ -1,267 +1,6 @@
1
- #!/usr/bin/env zsh
2
- # Create or checkout feature branches in Pennyfarthing repos
3
- # Idempotent, worktree-aware, branches from develop
4
-
1
+ #!/usr/bin/env bash
2
+ # DEPRECATED: Use `pf git branches` instead.
3
+ # This shim forwards to the Python CLI.
5
4
  set -e
6
-
7
- # Load environment
8
- if [ -f .env ]; then
9
- set -a; source .env; set +a
10
- elif [ -f ../.env ]; then
11
- set -a; source ../.env; set +a
12
- fi
13
-
14
- show_help() {
15
- cat << EOF
16
- Create Feature Branches - Idempotent branch creation/checkout
17
-
18
- Usage: ./create-feature-branches.sh <branch-name> [repos]
19
-
20
- Arguments:
21
- branch-name Branch name (e.g., feat/11-2-file-preview)
22
- repos Which repos to branch (default: all)
23
- Options: api, ui, all
24
-
25
- Repo Options:
26
- api - Pennyfarthing-api only
27
- ui - Pennyfarthing-ui only
28
- all - both repos (default)
29
-
30
- Examples:
31
- # All repos (default)
32
- ./create-feature-branches.sh feat/cross-repo-feature
33
-
34
- # Pennyfarthing UI only
35
- ./create-feature-branches.sh feat/11-2-ui-component ui
36
-
37
- # Pennyfarthing API only
38
- ./create-feature-branches.sh fix/validation-bug api
39
-
40
- Behavior:
41
- - Idempotent: Checks out existing branches or creates new ones
42
- - Worktree-aware: Detects main checkout vs worktree
43
- - Always branches from develop
44
- - Fetches latest develop before branching
45
-
46
- EOF
47
- }
48
-
49
- if [ -z "$1" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
50
- show_help
51
- exit 0
52
- fi
53
-
54
- BRANCH_NAME="$1"
55
- REPOS="${2:-all}"
56
-
57
- # Validate repos parameter
58
- if [[ ! "$REPOS" =~ ^(api|ui|all)$ ]]; then
59
- echo "❌ Error: repos must be one of: api, ui, all"
60
- echo " Got: $REPOS"
61
- echo ""
62
- echo "Options:"
63
- echo " api - Pennyfarthing-api only"
64
- echo " ui - Pennyfarthing-ui only"
65
- echo " all - both repos (default)"
66
- exit 1
67
- fi
68
-
69
- # Detect if we're in a worktree
70
- CURRENT_DIR=$(pwd)
71
- if [[ "$CURRENT_DIR" == *"/worktrees/"* ]]; then
72
- # Extract worktree name from path
73
- WORKTREE_NAME=$(echo "$CURRENT_DIR" | sed -E 's|.*/worktrees/([^/]+).*|\1|')
74
- REPO_BASE="$PROJECT_ROOT/worktrees/$WORKTREE_NAME"
75
- echo "📂 Detected worktree: $WORKTREE_NAME"
76
- else
77
- REPO_BASE="$PROJECT_ROOT"
78
- echo "📂 Using main checkout"
79
- fi
80
-
81
- # Array to track processed repos for verification
82
- declare -a PROCESSED_REPOS
83
-
84
- # Function to create or checkout branch in a repo
85
- create_or_checkout_branch() {
86
- local repo_path=$1
87
- local repo_name=$2
88
-
89
- if [ ! -d "$repo_path" ]; then
90
- echo "⚠️ Skipping $repo_name: directory not found at $repo_path"
91
- return
92
- fi
93
-
94
- cd "$repo_path"
95
-
96
- echo ""
97
- echo "🔧 Processing $repo_name..."
98
-
99
- # Fetch latest from remote
100
- echo " Fetching from origin..."
101
- git fetch origin --quiet
102
-
103
- # Check if branch exists locally
104
- if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
105
- echo " ✅ Branch exists locally, checking out: $BRANCH_NAME"
106
- git checkout "$BRANCH_NAME"
107
- # Check if branch exists on remote
108
- elif git show-ref --verify --quiet "refs/remotes/origin/$BRANCH_NAME"; then
109
- echo " ✅ Branch exists on remote, checking out and tracking: $BRANCH_NAME"
110
- git checkout -b "$BRANCH_NAME" "origin/$BRANCH_NAME"
111
- else
112
- # Branch doesn't exist, create from develop
113
- echo " 🌿 Creating new branch from develop: $BRANCH_NAME"
114
-
115
- # Make sure we have latest develop
116
- git fetch origin develop:develop --quiet 2>/dev/null || true
117
-
118
- # Checkout develop first
119
- if git show-ref --verify --quiet "refs/heads/develop"; then
120
- git checkout develop --quiet
121
- git pull origin develop --quiet
122
- else
123
- echo " ⚠️ Local develop doesn't exist, fetching from remote"
124
- git fetch origin develop:develop --quiet
125
- git checkout develop --quiet
126
- fi
127
-
128
- # Create new branch
129
- git checkout -b "$BRANCH_NAME"
130
- echo " ✅ Created: $BRANCH_NAME"
131
- fi
132
-
133
- # Show current status
134
- CURRENT_BRANCH=$(git branch --show-current)
135
- echo " 📍 Now on: $CURRENT_BRANCH"
136
-
137
- # Track this repo for verification
138
- PROCESSED_REPOS+=("$repo_path:$repo_name")
139
- }
140
-
141
- echo "🌿 Creating/checking out feature branches..."
142
- echo " Branch: $BRANCH_NAME"
143
- echo " Repos: $REPOS"
144
-
145
- # Process repos based on selection
146
- # When processing multiple repos, run in parallel for faster network I/O
147
- case "$REPOS" in
148
- api)
149
- create_or_checkout_branch "$REPO_BASE/Pennyfarthing-api" "Pennyfarthing-api"
150
- ;;
151
- ui)
152
- create_or_checkout_branch "$REPO_BASE/Pennyfarthing-ui" "Pennyfarthing-ui"
153
- ;;
154
- all)
155
- # Parallel execution for both repos
156
- tmpdir=$(mktemp -d)
157
- trap "rm -rf '$tmpdir'" EXIT
158
- HAD_ERRORS=false
159
-
160
- # Run both in parallel, capturing output
161
- # Write to separate files to avoid race condition on shared file
162
- (
163
- create_or_checkout_branch "$REPO_BASE/Pennyfarthing-api" "Pennyfarthing-api"
164
- echo "$REPO_BASE/Pennyfarthing-api:Pennyfarthing-api" > "$tmpdir/api.processed"
165
- ) > "$tmpdir/api.out" 2>&1 &
166
- pid_api=$!
167
-
168
- (
169
- create_or_checkout_branch "$REPO_BASE/Pennyfarthing-ui" "Pennyfarthing-ui"
170
- echo "$REPO_BASE/Pennyfarthing-ui:Pennyfarthing-ui" > "$tmpdir/ui.processed"
171
- ) > "$tmpdir/ui.out" 2>&1 &
172
- pid_ui=$!
173
-
174
- # Wait for both and capture exit codes
175
- wait $pid_api; rc_api=$?
176
- wait $pid_ui; rc_ui=$?
177
-
178
- # Show output in order
179
- [ -f "$tmpdir/api.out" ] && cat "$tmpdir/api.out"
180
- [ -f "$tmpdir/ui.out" ] && cat "$tmpdir/ui.out"
181
-
182
- # Rebuild PROCESSED_REPOS from separate files (avoids race condition)
183
- [ -f "$tmpdir/api.processed" ] && PROCESSED_REPOS+=("$(cat "$tmpdir/api.processed")")
184
- [ -f "$tmpdir/ui.processed" ] && PROCESSED_REPOS+=("$(cat "$tmpdir/ui.processed")")
185
-
186
- # Check for failures
187
- if [ $rc_api -ne 0 ] || [ $rc_ui -ne 0 ]; then
188
- echo "⚠️ Some repos had errors"
189
- HAD_ERRORS=true
190
- fi
191
- ;;
192
- esac
193
-
194
- echo ""
195
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
196
- echo "🔍 Verification Summary"
197
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
198
-
199
- # Verify each processed repo
200
- for repo_info in "${PROCESSED_REPOS[@]}"; do
201
- repo_path="${repo_info%%:*}"
202
- repo_name="${repo_info##*:}"
203
-
204
- if [ -d "$repo_path" ]; then
205
- cd "$repo_path"
206
-
207
- echo ""
208
- echo "📦 $repo_name"
209
- echo " Path: $repo_path"
210
-
211
- # Current branch
212
- CURRENT_BRANCH=$(git branch --show-current)
213
- echo " Branch: $CURRENT_BRANCH"
214
-
215
- # Check if branch matches expected
216
- if [ "$CURRENT_BRANCH" = "$BRANCH_NAME" ]; then
217
- echo " ✅ Branch matches: $BRANCH_NAME"
218
- else
219
- echo " ⚠️ Branch mismatch! Expected: $BRANCH_NAME, Got: $CURRENT_BRANCH"
220
- fi
221
-
222
- # Latest commit
223
- COMMIT_INFO=$(git log -1 --format="%h - %s" 2>/dev/null)
224
- echo " Commit: $COMMIT_INFO"
225
-
226
- # Check remote tracking
227
- UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null || echo "none")
228
- if [ "$UPSTREAM" != "none" ]; then
229
- echo " Remote: $UPSTREAM"
230
-
231
- # Check if up to date with remote
232
- git fetch origin "$CURRENT_BRANCH" --quiet 2>/dev/null || true
233
- LOCAL=$(git rev-parse @ 2>/dev/null)
234
- REMOTE=$(git rev-parse @{u} 2>/dev/null || echo "none")
235
-
236
- if [ "$LOCAL" = "$REMOTE" ]; then
237
- echo " Status: ✅ Up to date with remote"
238
- elif [ "$REMOTE" = "none" ]; then
239
- echo " Status: ⚠️ No remote branch yet (push needed)"
240
- else
241
- BEHIND=$(git rev-list --count HEAD..@{u} 2>/dev/null || echo "0")
242
- AHEAD=$(git rev-list --count @{u}..HEAD 2>/dev/null || echo "0")
243
- if [ "$AHEAD" -gt 0 ] && [ "$BEHIND" -gt 0 ]; then
244
- echo " Status: ⚠️ Diverged ($AHEAD ahead, $BEHIND behind)"
245
- elif [ "$AHEAD" -gt 0 ]; then
246
- echo " Status: ⬆️ $AHEAD commit(s) ahead of remote"
247
- elif [ "$BEHIND" -gt 0 ]; then
248
- echo " Status: ⬇️ $BEHIND commit(s) behind remote"
249
- fi
250
- fi
251
- else
252
- echo " Remote: none (local branch only)"
253
- echo " Status: ⚠️ Not tracking remote (push with -u needed)"
254
- fi
255
- fi
256
- done
257
-
258
- echo ""
259
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
260
- if [ "$HAD_ERRORS" = true ]; then
261
- echo "⚠️ Done with errors. Check output above."
262
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
263
- exit 1
264
- else
265
- echo "✅ Done! All branches verified and ready."
266
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
267
- fi
5
+ echo "DEPRECATED: create-feature-branches.sh — use 'pf git branches' instead" >&2
6
+ exec pf git branches "$@"