@pennyfarthing/core 11.1.1 → 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 (160) hide show
  1. package/README.md +8 -8
  2. package/package.json +1 -1
  3. package/packages/core/dist/server/otlp-receiver.d.ts +16 -11
  4. package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
  5. package/packages/core/dist/server/otlp-receiver.js +185 -24
  6. package/packages/core/dist/server/otlp-receiver.js.map +1 -1
  7. package/packages/core/dist/server/otlp-receiver.test.d.ts +21 -0
  8. package/packages/core/dist/server/otlp-receiver.test.d.ts.map +1 -0
  9. package/packages/core/dist/server/otlp-receiver.test.js +446 -0
  10. package/packages/core/dist/server/otlp-receiver.test.js.map +1 -0
  11. package/packages/core/dist/shared/portrait-resolver.d.ts +9 -0
  12. package/packages/core/dist/shared/portrait-resolver.d.ts.map +1 -1
  13. package/packages/core/dist/shared/portrait-resolver.js +27 -0
  14. package/packages/core/dist/shared/portrait-resolver.js.map +1 -1
  15. package/packages/core/dist/shared/portrait-resolver.test.js +47 -1
  16. package/packages/core/dist/shared/portrait-resolver.test.js.map +1 -1
  17. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts +13 -0
  18. package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts.map +1 -0
  19. package/packages/core/dist/shared/tandem-portrait-inventory.test.js +126 -0
  20. package/packages/core/dist/shared/tandem-portrait-inventory.test.js.map +1 -0
  21. package/pennyfarthing-dist/agents/dev.md +1 -1
  22. package/pennyfarthing-dist/agents/reviewer.md +1 -1
  23. package/pennyfarthing-dist/agents/sm-setup.md +1 -1
  24. package/pennyfarthing-dist/agents/sm.md +2 -2
  25. package/pennyfarthing-dist/agents/tea.md +1 -1
  26. package/pennyfarthing-dist/agents/testing-runner.md +2 -1
  27. package/pennyfarthing-dist/commands/pf-chore.md +2 -2
  28. package/pennyfarthing-dist/commands/pf-standalone.md +7 -2
  29. package/pennyfarthing-dist/guides/agent-behavior.md +1 -1
  30. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +1 -1
  31. package/pennyfarthing-dist/guides/bikerack.md +3 -3
  32. package/pennyfarthing-dist/guides/hooks.md +1 -1
  33. package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
  34. package/pennyfarthing-dist/guides/xml-tags.md +2 -2
  35. package/pennyfarthing-dist/scripts/README.md +1 -1
  36. package/pennyfarthing-dist/scripts/core/check-context.sh +1 -1
  37. package/pennyfarthing-dist/scripts/git/README.md +24 -14
  38. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +5 -266
  39. package/pennyfarthing-dist/scripts/git/git-status-all.sh +5 -151
  40. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +6 -144
  41. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +5 -496
  42. package/pennyfarthing-dist/scripts/hooks/README.md +1 -1
  43. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +1 -1
  44. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +9 -11
  45. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +1 -1
  46. package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +76 -0
  47. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +4 -221
  48. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +5 -13
  49. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +4 -123
  50. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +4 -33
  51. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +4 -156
  52. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +4 -131
  53. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +4 -249
  54. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +4 -160
  55. package/pennyfarthing-dist/skills/pf-bc/usage.md +1 -1
  56. package/pennyfarthing-dist/skills/pf-jira/examples.md +5 -2
  57. package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -16
  58. package/pennyfarthing-dist/skills/pf-workflow/skill.md +9 -12
  59. package/pennyfarthing-dist/skills/pf-workflow/usage.md +33 -8
  60. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +18 -6
  61. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
  62. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
  63. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
  64. package/pennyfarthing-dist/workflows/review-tandem.yaml +65 -0
  65. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +16 -8
  66. package/pennyfarthing_scripts/CLAUDE.md +26 -4
  67. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  68. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  69. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  70. package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
  71. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  72. package/pennyfarthing_scripts/bc/cli.py +3 -5
  73. package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
  74. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  75. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  76. package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
  77. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  78. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  79. package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
  80. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  81. package/pennyfarthing_scripts/bikerack/__pycache__/portrait.cpython-314.pyc +0 -0
  82. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  83. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  84. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  85. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  86. package/pennyfarthing_scripts/bikerack/background_panel.py +86 -5
  87. package/pennyfarthing_scripts/bikerack/base_panel.py +62 -0
  88. package/pennyfarthing_scripts/bikerack/changed_panel.py +32 -28
  89. package/pennyfarthing_scripts/bikerack/debug_panel.py +31 -1
  90. package/pennyfarthing_scripts/bikerack/diffs_panel.py +74 -17
  91. package/pennyfarthing_scripts/bikerack/git_panel.py +103 -33
  92. package/pennyfarthing_scripts/bikerack/launcher.py +15 -15
  93. package/pennyfarthing_scripts/bikerack/progress_panel.py +315 -0
  94. package/pennyfarthing_scripts/bikerack/sprint_panel.py +158 -26
  95. package/pennyfarthing_scripts/bikerack/tui.py +336 -30
  96. package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
  97. package/pennyfarthing_scripts/cli.py +37 -65
  98. package/pennyfarthing_scripts/consultation/__init__.py +1 -0
  99. package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
  100. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  101. package/pennyfarthing_scripts/consultation/cli.py +149 -0
  102. package/pennyfarthing_scripts/consultation/dialogue_manager.py +417 -0
  103. package/pennyfarthing_scripts/context.py +3 -3
  104. package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
  105. package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
  106. package/pennyfarthing_scripts/git/__init__.py +12 -1
  107. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  108. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  109. package/pennyfarthing_scripts/git/__pycache__/hooks_installer.cpython-314.pyc +0 -0
  110. package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
  111. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  112. package/pennyfarthing_scripts/git/__pycache__/worktree.cpython-314.pyc +0 -0
  113. package/pennyfarthing_scripts/git/create_branches.py +3 -4
  114. package/pennyfarthing_scripts/git/hooks_installer.py +152 -0
  115. package/pennyfarthing_scripts/git/repos.py +196 -0
  116. package/pennyfarthing_scripts/git/status_all.py +27 -11
  117. package/pennyfarthing_scripts/git/worktree.py +302 -0
  118. package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
  119. package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
  120. package/pennyfarthing_scripts/git_group/cli.py +143 -40
  121. package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
  122. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  123. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  124. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  125. package/pennyfarthing_scripts/handoff/complete_phase.py +12 -0
  126. package/pennyfarthing_scripts/handoff/resolve_gate.py +5 -14
  127. package/pennyfarthing_scripts/hooks.py +3 -17
  128. package/pennyfarthing_scripts/pretooluse_hook.py +1 -1
  129. package/pennyfarthing_scripts/prime/__pycache__/heatmap.cpython-314.pyc +0 -0
  130. package/pennyfarthing_scripts/prime/heatmap.py +655 -0
  131. package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
  132. package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
  133. package/pennyfarthing_scripts/session_start_hook.py +1 -1
  134. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  135. package/pennyfarthing_scripts/sprint/loader.py +15 -1
  136. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  137. package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
  138. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  139. package/pennyfarthing_scripts/tests/test_bikerack.py +51 -51
  140. package/pennyfarthing_scripts/tests/test_dialogue_manager.py +811 -0
  141. package/pennyfarthing_scripts/tests/test_handoff_cli.py +16 -11
  142. package/pennyfarthing_scripts/tests/test_workflow_check.py +2 -3
  143. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  144. package/pennyfarthing_scripts/validate/adapters/tandem_awareness.py +254 -0
  145. package/pennyfarthing_scripts/validate/cli.py +17 -5
  146. package/pennyfarthing_scripts/workflow/__init__.py +40 -0
  147. package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
  148. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  149. package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
  150. package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
  151. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
  152. package/pennyfarthing_scripts/workflow/cli.py +1099 -0
  153. package/pennyfarthing_scripts/workflow/helpers.py +241 -0
  154. package/pennyfarthing_scripts/{workflow.py → workflow/scale.py} +0 -104
  155. package/pennyfarthing_scripts/workflow/state.py +112 -0
  156. package/pennyfarthing-dist/skills/pf-workflow/scripts/list-workflows.sh +0 -91
  157. package/pennyfarthing-dist/skills/pf-workflow/scripts/resume-workflow.sh +0 -163
  158. package/pennyfarthing-dist/skills/pf-workflow/scripts/show-workflow.sh +0 -138
  159. package/pennyfarthing-dist/skills/pf-workflow/scripts/start-workflow.sh +0 -273
  160. package/pennyfarthing-dist/skills/pf-workflow/scripts/workflow-status.sh +0 -167
@@ -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 "$@"
@@ -1,152 +1,6 @@
1
- #!/usr/bin/env zsh
2
- # Show git status across all repos
3
- # Usage: ./scripts/git-status-all.sh [--brief]
4
- #
5
- # Shows: branch, status, unpushed commits for all repos
6
- # Reads repo configuration from .pennyfarthing/repos.yaml
7
-
1
+ #!/usr/bin/env bash
2
+ # DEPRECATED: Use `pf git status` instead.
3
+ # This shim forwards to the Python CLI.
8
4
  set -e
9
-
10
- # Source environment (inline to avoid argument passing issues)
11
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
12
- if [ -f "$SCRIPT_DIR/../.env" ]; then
13
- set -a; source "$SCRIPT_DIR/../.env"; set +a
14
- fi
15
-
16
- # Fallback if PROJECT_ROOT not set
17
- PROJECT_ROOT="${PROJECT_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
18
-
19
- # Source repo utilities for dynamic repo configuration
20
- source "$SCRIPT_DIR/../misc/repo-utils.sh"
21
-
22
- # Colors
23
- GREEN='\033[0;32m'
24
- YELLOW='\033[1;33m'
25
- BLUE='\033[0;34m'
26
- RED='\033[0;31m'
27
- NC='\033[0m'
28
-
29
- BRIEF=false
30
- if [ "${1:-}" = "--brief" ] || [ "${1:-}" = "-b" ]; then
31
- BRIEF=true
32
- fi
33
-
34
- cd "$PROJECT_ROOT"
35
-
36
- show_repo_status() {
37
- local repo_name=$1
38
- local repo_dir=$2 # Note: can't use 'path' - it's a zsh special variable
39
-
40
- if [ ! -d "$repo_dir/.git" ] && [ ! -d "$repo_dir" ]; then
41
- return
42
- fi
43
-
44
- local branch=$(git -C "$repo_dir" branch --show-current 2>/dev/null || echo "detached")
45
- local git_status=$(git -C "$repo_dir" status --short 2>/dev/null)
46
- local git_status_count=$(echo "$git_status" | grep -c . 2>/dev/null); git_status_count=${git_status_count:-0}
47
- local unpushed=$(git -C "$repo_dir" log origin/develop..HEAD --oneline 2>/dev/null | head -5)
48
- local unpushed_count=$(git -C "$repo_dir" log origin/develop..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
49
-
50
- if $BRIEF; then
51
- # One-line format
52
- local status_indicator=""
53
- [ "$git_status_count" -gt 0 ] && status_indicator="${YELLOW}M${NC}" || status_indicator="${GREEN}✓${NC}"
54
- local push_indicator=""
55
- [ "$unpushed_count" -gt 0 ] && push_indicator=" ${BLUE}↑${unpushed_count}${NC}"
56
- echo -e "$repo_name: $branch $status_indicator$push_indicator"
57
- else
58
- echo -e "${BLUE}=== $repo_name ===${NC}"
59
- echo -e "Branch: ${GREEN}$branch${NC}"
60
-
61
- if [ -n "$git_status" ]; then
62
- echo -e "${YELLOW}Changes:${NC}"
63
- echo "$git_status" | head -10 | sed 's/^/ /'
64
- [ "$git_status_count" -gt 10 ] && echo " ... and $((git_status_count - 10)) more"
65
- else
66
- echo -e "${GREEN}Clean${NC}"
67
- fi
68
-
69
- if [ "$unpushed_count" -gt 0 ]; then
70
- echo -e "${BLUE}Unpushed ($unpushed_count):${NC}"
71
- echo "$unpushed" | sed 's/^/ /'
72
- [ "$unpushed_count" -gt 5 ] && echo " ... and $((unpushed_count - 5)) more"
73
- fi
74
- echo ""
75
- fi
76
- }
77
-
78
- if ! $BRIEF; then
79
- echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
80
- echo -e "${BLUE} Git Status - All Repos${NC}"
81
- echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
82
- echo ""
83
- fi
84
-
85
- # Check each repo from configuration (parallelized for performance)
86
- repo_count=$(get_repo_count)
87
- if [[ "$repo_count" -eq 0 ]]; then
88
- # No repos configured, just show current directory
89
- show_repo_status "Project" "$PROJECT_ROOT"
90
- else
91
- # Create temp dir for parallel output capture
92
- tmpdir=$(mktemp -d)
93
- trap "rm -rf '$tmpdir'" EXIT
94
-
95
- # Launch status checks in parallel
96
- for repo in $(get_repos); do
97
- repo_path=$(get_repo_full_path "$repo")
98
- (show_repo_status "$repo" "$repo_path" > "$tmpdir/$repo.out" 2>&1) &
99
- done
100
- wait
101
-
102
- # Output results in order
103
- for repo in $(get_repos); do
104
- [ -f "$tmpdir/$repo.out" ] && cat "$tmpdir/$repo.out"
105
- done
106
- fi
107
-
108
- if ! $BRIEF; then
109
- echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
110
-
111
- # Summary
112
- total_changes=0
113
- total_unpushed=0
114
-
115
- if [[ "$repo_count" -eq 0 ]]; then
116
- # No repos configured, just check current directory
117
- count=$(git -C "$PROJECT_ROOT" status --short 2>/dev/null | wc -l | tr -d ' ')
118
- total_changes=$((total_changes + count))
119
- unpushed=$(git -C "$PROJECT_ROOT" log origin/develop..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
120
- total_unpushed=$((total_unpushed + unpushed))
121
- else
122
- # Parallelize summary collection
123
- summary_tmp=$(mktemp -d)
124
- for repo in $(get_repos); do
125
- repo_path=$(get_repo_full_path "$repo")
126
- (
127
- [ -d "$repo_path/.git" ] || [ -d "$repo_path" ] || exit 0
128
- count=$(git -C "$repo_path" status --short 2>/dev/null | wc -l | tr -d ' ')
129
- unpushed=$(git -C "$repo_path" log origin/develop..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
130
- echo "$count $unpushed" > "$summary_tmp/$repo.count"
131
- ) &
132
- done
133
- wait
134
-
135
- # Aggregate results
136
- for repo in $(get_repos); do
137
- if [ -f "$summary_tmp/$repo.count" ]; then
138
- read count unpushed < "$summary_tmp/$repo.count"
139
- total_changes=$((total_changes + count))
140
- total_unpushed=$((total_unpushed + unpushed))
141
- fi
142
- done
143
- rm -rf "$summary_tmp"
144
- fi
145
-
146
- if [ "$total_changes" -eq 0 ] && [ "$total_unpushed" -eq 0 ]; then
147
- echo -e "${GREEN}✅ All repos clean and pushed${NC}"
148
- else
149
- [ "$total_changes" -gt 0 ] && echo -e "${YELLOW}$total_changes uncommitted change(s)${NC}"
150
- [ "$total_unpushed" -gt 0 ] && echo -e "${BLUE}$total_unpushed unpushed commit(s)${NC}"
151
- fi
152
- fi
5
+ echo "DEPRECATED: git-status-all.sh — use 'pf git status' instead" >&2
6
+ exec pf git status "$@"
@@ -1,144 +1,6 @@
1
- #!/bin/bash
2
- # install-git-hooks.sh - Install Pennyfarthing git hooks for framework development
3
- #
4
- # Usage: ./pennyfarthing-dist/scripts/install-git-hooks.sh
5
- #
6
- # For the pennyfarthing framework repo and orchestrator repos that inline it.
7
- # End-user projects use `pennyfarthing init` which copies hooks from node_modules.
8
- # This script creates .d/ directories with symlinks so hook changes in
9
- # pennyfarthing-dist/ take effect immediately.
10
-
11
- set -euo pipefail
12
-
13
- # Self-locate and set up PROJECT_ROOT
14
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
15
- source "$SCRIPT_DIR/../lib/find-root.sh"
16
- HOOKS_SOURCE="$PROJECT_ROOT/pennyfarthing-dist/scripts/hooks"
17
- HOOKS_DEST="$PROJECT_ROOT/.git/hooks"
18
-
19
- DISPATCHER_MARKER="pennyfarthing-dispatcher"
20
- PF_PREFIX="10"
21
- MIGRATED_PREFIX="50"
22
-
23
- # Check we're in a repo with pennyfarthing-dist (framework or orchestrator)
24
- if [[ ! -d "$PROJECT_ROOT/pennyfarthing-dist" ]]; then
25
- echo "Error: This script requires pennyfarthing-dist/ at the project root"
26
- echo " (framework repo or orchestrator with inlined pennyfarthing/)"
27
- echo " End-user projects should use: pennyfarthing init"
28
- exit 1
29
- fi
30
-
31
- # Check .git exists
32
- if [[ ! -d "$PROJECT_ROOT/.git" ]]; then
33
- echo "Error: Not a git repository"
34
- exit 1
35
- fi
36
-
37
- echo "Installing git hooks with .d/ dispatcher pattern..."
38
- echo " Source: pennyfarthing-dist/scripts/hooks/"
39
- echo " Dest: .git/hooks/"
40
- echo ""
41
-
42
- # Shared dispatcher template — single source of truth
43
- DISPATCHER_TEMPLATE="$PROJECT_ROOT/pennyfarthing-dist/scripts/hooks/dispatcher-template.sh"
44
-
45
- if [[ ! -f "$DISPATCHER_TEMPLATE" ]]; then
46
- echo "Error: dispatcher-template.sh not found at $DISPATCHER_TEMPLATE"
47
- exit 1
48
- fi
49
-
50
- # Generate a dispatcher script for a given hook name
51
- generate_dispatcher() {
52
- local hook_name="$1"
53
- sed "s/__HOOK_NAME__/${hook_name}/g" "$DISPATCHER_TEMPLATE"
54
- }
55
-
56
- # Define hooks to install
57
- HOOKS=(
58
- "pre-commit.sh:pre-commit"
59
- "pre-push.sh:pre-push"
60
- "post-merge.sh:post-merge"
61
- )
62
-
63
- for hook_pair in "${HOOKS[@]}"; do
64
- source_file="${hook_pair%%:*}"
65
- dest_name="${hook_pair##*:}"
66
-
67
- source_path="$HOOKS_SOURCE/$source_file"
68
- dest_path="$HOOKS_DEST/$dest_name"
69
- d_dir="$HOOKS_DEST/${dest_name}.d"
70
- pf_hook_name="${PF_PREFIX}-pennyfarthing-${dest_name}.sh"
71
- pf_hook_path="${d_dir}/${pf_hook_name}"
72
-
73
- if [[ ! -f "$source_path" ]]; then
74
- echo " SKIP $dest_name (source not found)"
75
- continue
76
- fi
77
-
78
- # Create .d/ directory
79
- mkdir -p "$d_dir"
80
-
81
- # Handle existing hook at the dest path
82
- if [[ -e "$dest_path" ]]; then
83
- if [[ -f "$dest_path" ]] && grep -q "$DISPATCHER_MARKER" "$dest_path" 2>/dev/null; then
84
- echo " OK $dest_name dispatcher (already installed)"
85
- elif [[ -L "$dest_path" ]]; then
86
- # Old-style symlink — migrate to .d/ pattern
87
- rm "$dest_path"
88
- generate_dispatcher "$dest_name" > "$dest_path"
89
- chmod 755 "$dest_path"
90
- echo " UPD $dest_name → dispatcher"
91
- elif [[ -f "$dest_path" ]]; then
92
- existing_content="$(cat "$dest_path")"
93
- if echo "$existing_content" | grep -q "pennyfarthing"; then
94
- # Old pennyfarthing single-file hook — replace with dispatcher
95
- generate_dispatcher "$dest_name" > "$dest_path"
96
- chmod 755 "$dest_path"
97
- echo " UPD $dest_name → dispatcher (was single-file pf hook)"
98
- else
99
- # Non-pennyfarthing hook — migrate into .d/
100
- migrated_name="${MIGRATED_PREFIX}-migrated-${dest_name}.sh"
101
- migrated_path="${d_dir}/${migrated_name}"
102
- if [[ ! -f "$migrated_path" ]]; then
103
- mv "$dest_path" "$migrated_path"
104
- chmod 755 "$migrated_path"
105
- echo " MIG $dest_name → ${dest_name}.d/${migrated_name}"
106
- fi
107
- generate_dispatcher "$dest_name" > "$dest_path"
108
- chmod 755 "$dest_path"
109
- echo " NEW $dest_name dispatcher"
110
- fi
111
- fi
112
- else
113
- # No existing hook — install fresh dispatcher
114
- generate_dispatcher "$dest_name" > "$dest_path"
115
- chmod 755 "$dest_path"
116
- echo " NEW $dest_name dispatcher"
117
- fi
118
-
119
- # Symlink pennyfarthing hook into .d/ (framework dev — symlink for live edits)
120
- # From .git/hooks/{hook}.d/ we need ../../.../pennyfarthing-dist/scripts/hooks/
121
- relative_path="../../../pennyfarthing-dist/scripts/hooks/$source_file"
122
-
123
- if [[ -L "$pf_hook_path" ]]; then
124
- current_target=$(readlink "$pf_hook_path")
125
- if [[ "$current_target" == "$relative_path" ]]; then
126
- echo " OK ${dest_name}.d/${pf_hook_name} (already linked)"
127
- else
128
- rm "$pf_hook_path"
129
- ln -sf "$relative_path" "$pf_hook_path"
130
- echo " UPD ${dest_name}.d/${pf_hook_name} → $relative_path"
131
- fi
132
- elif [[ -f "$pf_hook_path" ]]; then
133
- # Regular file — replace with symlink for dev
134
- rm "$pf_hook_path"
135
- ln -sf "$relative_path" "$pf_hook_path"
136
- echo " UPD ${dest_name}.d/${pf_hook_name} → $relative_path (was copy)"
137
- else
138
- ln -sf "$relative_path" "$pf_hook_path"
139
- echo " NEW ${dest_name}.d/${pf_hook_name} → $relative_path"
140
- fi
141
- done
142
-
143
- echo ""
144
- echo "Done. Verify with: ls -la .git/hooks/*.d/"
1
+ #!/usr/bin/env bash
2
+ # DEPRECATED: Use `pf git install-hooks` instead.
3
+ # This shim forwards to the Python CLI.
4
+ set -e
5
+ echo "DEPRECATED: install-git-hooks.sh — use 'pf git install-hooks' instead" >&2
6
+ exec pf git install-hooks "$@"