@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
@@ -1,163 +0,0 @@
1
- #!/bin/bash
2
- # Resume a stepped workflow from last completed step
3
- # Usage: .pennyfarthing/scripts/workflow/resume-workflow.sh [name]
4
- #
5
- # If no name provided, detects from active session
6
-
7
- set -euo pipefail
8
-
9
- # PROJECT_ROOT should be set by find-root.sh, but find it if not
10
- if [[ -z "${PROJECT_ROOT:-}" ]]; then
11
- d="$PWD"
12
- while [[ ! -d "$d/.claude" ]] && [[ "$d" != "/" ]]; do
13
- d="$(dirname "$d")"
14
- done
15
- PROJECT_ROOT="$d"
16
- fi
17
-
18
- WORKFLOWS_DIR="$PROJECT_ROOT/.pennyfarthing/workflows"
19
- SESSION_DIR="$PROJECT_ROOT/.session"
20
-
21
- if ! command -v yq &> /dev/null; then
22
- echo "Error: yq is required but not installed"
23
- echo "Install with: brew install yq"
24
- exit 1
25
- fi
26
-
27
- WORKFLOW_NAME="${1:-}"
28
-
29
- # If no name, try to detect from session
30
- if [[ -z "$WORKFLOW_NAME" ]]; then
31
- # Look for workflow session files
32
- SESSION_FILE=$(find "$SESSION_DIR" -maxdepth 1 -name "*-workflow-session.md" 2>/dev/null | head -1)
33
-
34
- if [[ -z "$SESSION_FILE" ]]; then
35
- echo "# Resume Stepped Workflow"
36
- echo ""
37
- echo "No active workflow session found."
38
- echo ""
39
- echo "Use \`/workflow start <name>\` to begin a new workflow."
40
- exit 1
41
- fi
42
-
43
- # Extract workflow name from session
44
- WORKFLOW_NAME=$(grep -E "^\*\*Workflow:\*\*" "$SESSION_FILE" 2>/dev/null | sed 's/\*\*Workflow:\*\* //' | tr -d ' ')
45
-
46
- if [[ -z "$WORKFLOW_NAME" ]]; then
47
- # Try extracting from filename
48
- WORKFLOW_NAME=$(basename "$SESSION_FILE" | sed 's/-workflow-session.md//')
49
- fi
50
- else
51
- SESSION_FILE="$SESSION_DIR/${WORKFLOW_NAME}-workflow-session.md"
52
- fi
53
-
54
- if [[ ! -f "$SESSION_FILE" ]]; then
55
- echo "Error: No session found for workflow '$WORKFLOW_NAME'"
56
- echo ""
57
- echo "Use \`/workflow start $WORKFLOW_NAME\` to begin."
58
- exit 1
59
- fi
60
-
61
- # Find workflow file
62
- WORKFLOW_FILE=""
63
- if [[ -f "$WORKFLOWS_DIR/${WORKFLOW_NAME}.yaml" ]]; then
64
- WORKFLOW_FILE="$WORKFLOWS_DIR/${WORKFLOW_NAME}.yaml"
65
- elif [[ -f "$WORKFLOWS_DIR/${WORKFLOW_NAME}/workflow.yaml" ]]; then
66
- WORKFLOW_FILE="$WORKFLOWS_DIR/${WORKFLOW_NAME}/workflow.yaml"
67
- else
68
- echo "Error: Workflow definition '$WORKFLOW_NAME' not found"
69
- exit 1
70
- fi
71
-
72
- WORKFLOW_DIR=$(dirname "$WORKFLOW_FILE")
73
-
74
- # Parse session state
75
- CURRENT_STEP=$(grep -E "^\- \*\*Current Step:\*\*" "$SESSION_FILE" 2>/dev/null | sed 's/.*\*\* //' || echo "1")
76
- MODE=$(grep -E "^\- \*\*Mode:\*\*" "$SESSION_FILE" 2>/dev/null | sed 's/.*\*\* //' || echo "create")
77
- STATUS=$(grep -E "^\- \*\*Status:\*\*" "$SESSION_FILE" 2>/dev/null | sed 's/.*\*\* //' || echo "in_progress")
78
- STEPS_COMPLETED=$(grep -E "^\- \*\*Steps Completed:\*\*" "$SESSION_FILE" 2>/dev/null | sed 's/.*\*\* //' || echo "[]")
79
-
80
- # Check if workflow is complete
81
- if [[ "$STATUS" == "completed" ]]; then
82
- echo "# Workflow Complete: $WORKFLOW_NAME"
83
- echo ""
84
- echo "This workflow has already been completed."
85
- echo ""
86
- echo "To start a new session, delete the session file:"
87
- echo "\`\`\`bash"
88
- echo "rm \"$SESSION_FILE\""
89
- echo "\`\`\`"
90
- echo ""
91
- echo "Then run \`/workflow start $WORKFLOW_NAME\`"
92
- exit 0
93
- fi
94
-
95
- # Resolve steps path based on mode
96
- MODE_PATH=$(yq eval ".workflow.modes.$MODE // \"\"" "$WORKFLOW_FILE")
97
- if [[ -n "$MODE_PATH" && "$MODE_PATH" != "null" ]]; then
98
- STEPS_PATH="$MODE_PATH"
99
- else
100
- STEPS_PATH=$(yq eval '.workflow.steps.path' "$WORKFLOW_FILE")
101
- fi
102
-
103
- # Resolve relative path
104
- if [[ "$STEPS_PATH" == ./* ]]; then
105
- STEPS_PATH="$WORKFLOW_DIR/${STEPS_PATH#./}"
106
- elif [[ "$STEPS_PATH" != /* ]]; then
107
- STEPS_PATH="$PROJECT_ROOT/$STEPS_PATH"
108
- fi
109
-
110
- # Count steps
111
- STEP_COUNT=$(find "$STEPS_PATH" -maxdepth 1 -name "step-0*.md" -o -name "step-1*.md" 2>/dev/null | wc -l | tr -d ' ')
112
-
113
- # Find the current step file
114
- # Handle various naming: step-01.md, step-01-name.md, step-1-name.md
115
- PADDED_STEP=$(printf "%02d" "$CURRENT_STEP")
116
- STEP_FILE=$(find "$STEPS_PATH" -maxdepth 1 \( -name "step-${PADDED_STEP}*.md" -o -name "step-${CURRENT_STEP}-*.md" \) 2>/dev/null | sort | head -1)
117
-
118
- if [[ -z "$STEP_FILE" ]]; then
119
- echo "Error: Could not find step $CURRENT_STEP file in $STEPS_PATH"
120
- exit 1
121
- fi
122
-
123
- # Update last updated timestamp
124
- NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
125
- sed -i '' "s/^\- \*\*Last Updated:\*\*.*/- **Last Updated:** $NOW/" "$SESSION_FILE" 2>/dev/null || true
126
-
127
- # Calculate completion percentage
128
- COMPLETED_COUNT=$(echo "$STEPS_COMPLETED" | tr -cd ',' | wc -c | tr -d ' ')
129
- if [[ "$STEPS_COMPLETED" != "[]" ]]; then
130
- COMPLETED_COUNT=$((COMPLETED_COUNT + 1))
131
- fi
132
- if [[ "$STEP_COUNT" -gt 0 ]]; then
133
- COMPLETION_PCT=$((COMPLETED_COUNT * 100 / STEP_COUNT))
134
- else
135
- COMPLETION_PCT=0
136
- fi
137
-
138
- # Output resume info
139
- echo "# Resuming Workflow: $WORKFLOW_NAME"
140
- echo ""
141
- echo "**Mode:** $MODE"
142
- echo "**Progress:** Step $CURRENT_STEP of $STEP_COUNT ($COMPLETION_PCT% complete)"
143
- echo "**Steps Completed:** $STEPS_COMPLETED"
144
- echo "**Session:** $SESSION_FILE"
145
- echo ""
146
- echo "---"
147
- echo ""
148
- echo "## Step $CURRENT_STEP of $STEP_COUNT"
149
- echo ""
150
-
151
- # Output step content (strip frontmatter if present)
152
- if head -1 "$STEP_FILE" | grep -q "^---$"; then
153
- awk '/^---$/{if(++c==2){p=1;next}}p' "$STEP_FILE"
154
- else
155
- cat "$STEP_FILE"
156
- fi
157
-
158
- echo ""
159
- echo "---"
160
- echo ""
161
- echo "**Controls:**"
162
- echo "- \`C\` - Continue to next step"
163
- echo "- \`/workflow status\` - Check progress"
@@ -1,138 +0,0 @@
1
- #!/bin/bash
2
- # Show workflow details
3
- # Usage: .pennyfarthing/scripts/workflow/show-workflow.sh [name]
4
- # or: Invoked with PROJECT_ROOT already set
5
- #
6
- # If no name provided, shows current session's workflow
7
- # If name provided, shows that workflow's details
8
-
9
- set -euo pipefail
10
-
11
- # PROJECT_ROOT should be set by find-root.sh, but find it if not
12
- if [[ -z "${PROJECT_ROOT:-}" ]]; then
13
- d="$PWD"
14
- while [[ ! -d "$d/.claude" ]] && [[ "$d" != "/" ]]; do
15
- d="$(dirname "$d")"
16
- done
17
- PROJECT_ROOT="$d"
18
- fi
19
-
20
- WORKFLOWS_DIR="$PROJECT_ROOT/.pennyfarthing/workflows"
21
- SESSION_DIR="$PROJECT_ROOT/.session"
22
-
23
- if ! command -v yq &> /dev/null; then
24
- echo "Error: yq is required but not installed"
25
- echo "Install with: brew install yq"
26
- exit 1
27
- fi
28
-
29
- # Get workflow name from argument or session
30
- WORKFLOW_NAME="${1:-}"
31
-
32
- if [[ -z "$WORKFLOW_NAME" ]]; then
33
- # Try to get from current session (exclude archive directory)
34
- SESSION_FILE=$(find "$SESSION_DIR" -maxdepth 1 -name "*-session.md" 2>/dev/null | head -1)
35
- if [[ -n "$SESSION_FILE" ]]; then
36
- # Extract workflow from session file (look for **Workflow:** line)
37
- WORKFLOW_NAME=$(grep -E "^\*\*Workflow:\*\*" "$SESSION_FILE" 2>/dev/null | sed 's/.*\*\* //' | tr -d ' ' || echo "")
38
- if [[ -z "$WORKFLOW_NAME" ]]; then
39
- # Try alternate format (Workflow: value in tracking section)
40
- WORKFLOW_NAME=$(grep -E "^Workflow:" "$SESSION_FILE" 2>/dev/null | head -1 | cut -d: -f2 | tr -d ' ' || echo "")
41
- fi
42
- fi
43
-
44
- if [[ -z "$WORKFLOW_NAME" ]]; then
45
- echo "# Current Workflow"
46
- echo ""
47
- echo "No active session found. Showing default workflow (tdd)."
48
- echo ""
49
- WORKFLOW_NAME="tdd"
50
- else
51
- echo "# Current Session Workflow: $WORKFLOW_NAME"
52
- echo ""
53
- fi
54
- else
55
- echo "# Workflow: $WORKFLOW_NAME"
56
- echo ""
57
- fi
58
-
59
- WORKFLOW_FILE="$WORKFLOWS_DIR/${WORKFLOW_NAME}.yaml"
60
-
61
- if [[ ! -f "$WORKFLOW_FILE" ]]; then
62
- echo "Error: Workflow '$WORKFLOW_NAME' not found"
63
- echo ""
64
- echo "Available workflows:"
65
- for f in "$WORKFLOWS_DIR"/*.yaml; do
66
- [[ -f "$f" ]] || continue
67
- basename "$f" .yaml
68
- done
69
- exit 1
70
- fi
71
-
72
- # Extract workflow details
73
- DESC=$(yq eval '.workflow.description' "$WORKFLOW_FILE")
74
- VERSION=$(yq eval '.workflow.version' "$WORKFLOW_FILE")
75
-
76
- echo "**Description:** $DESC"
77
- echo "**Version:** $VERSION"
78
- echo ""
79
-
80
- # Show phases as a flow diagram
81
- echo "## Phase Flow"
82
- echo ""
83
- echo -n "\`\`\`"
84
- echo ""
85
-
86
- # Build phase flow string
87
- PHASES=""
88
- yq eval '.workflow.phases[].name' "$WORKFLOW_FILE" | while read -r phase; do
89
- if [[ -n "$PHASES" ]]; then
90
- echo -n " -> "
91
- fi
92
- echo -n "$phase"
93
- PHASES="$phase"
94
- done
95
- echo ""
96
- echo "\`\`\`"
97
- echo ""
98
-
99
- # Show phases table
100
- echo "## Phases"
101
- echo ""
102
- echo "| Phase | Agent | Gate |"
103
- echo "|-------|-------|------|"
104
-
105
- yq eval '.workflow.phases[] | .name + "|" + .agent + "|" + (.gate.type // "none")' "$WORKFLOW_FILE" | while IFS='|' read -r phase agent gate; do
106
- echo "| $phase | $agent | $gate |"
107
- done
108
-
109
- echo ""
110
-
111
- # Show triggers
112
- echo "## Triggers"
113
- echo ""
114
-
115
- TYPES=$(yq eval '.workflow.triggers.types // []' "$WORKFLOW_FILE")
116
- if [[ "$TYPES" != "[]" && "$TYPES" != "null" ]]; then
117
- echo "**Types:** $(yq eval '.workflow.triggers.types | join(", ")' "$WORKFLOW_FILE")"
118
- fi
119
-
120
- POINTS_MIN=$(yq eval '.workflow.triggers.points.min // ""' "$WORKFLOW_FILE")
121
- POINTS_MAX=$(yq eval '.workflow.triggers.points.max // ""' "$WORKFLOW_FILE")
122
-
123
- if [[ -n "$POINTS_MIN" && "$POINTS_MIN" != "null" ]]; then
124
- echo "**Points Min:** $POINTS_MIN"
125
- fi
126
- if [[ -n "$POINTS_MAX" && "$POINTS_MAX" != "null" ]]; then
127
- echo "**Points Max:** $POINTS_MAX"
128
- fi
129
-
130
- IS_DEFAULT=$(yq eval '.workflow.triggers.default // false' "$WORKFLOW_FILE")
131
- if [[ "$IS_DEFAULT" == "true" ]]; then
132
- echo "**Default:** yes (used when no other workflow matches)"
133
- fi
134
-
135
- TAGS=$(yq eval '.workflow.triggers.tags // []' "$WORKFLOW_FILE")
136
- if [[ "$TAGS" != "[]" && "$TAGS" != "null" ]]; then
137
- echo "**Tags:** $(yq eval '.workflow.triggers.tags | join(", ")' "$WORKFLOW_FILE")"
138
- fi
@@ -1,273 +0,0 @@
1
- #!/bin/bash
2
- # Start a stepped workflow
3
- # Usage: .pennyfarthing/scripts/workflow/start-workflow.sh <name> [--mode create|validate|edit]
4
- #
5
- # Creates a new workflow session and loads step 1.
6
- # For tri-modal workflows, --mode selects the step path (default: create)
7
-
8
- set -euo pipefail
9
-
10
- # PROJECT_ROOT should be set by find-root.sh, but find it if not
11
- if [[ -z "${PROJECT_ROOT:-}" ]]; then
12
- d="$PWD"
13
- while [[ ! -d "$d/.claude" ]] && [[ "$d" != "/" ]]; do
14
- d="$(dirname "$d")"
15
- done
16
- PROJECT_ROOT="$d"
17
- fi
18
-
19
- WORKFLOWS_DIR="$PROJECT_ROOT/.pennyfarthing/workflows"
20
- SESSION_DIR="$PROJECT_ROOT/.session"
21
-
22
- if ! command -v yq &> /dev/null; then
23
- echo "Error: yq is required but not installed"
24
- echo "Install with: brew install yq"
25
- exit 1
26
- fi
27
-
28
- # Parse arguments
29
- WORKFLOW_NAME=""
30
- MODE=""
31
- ARGS=("$@")
32
-
33
- i=0
34
- while [[ $i -lt ${#ARGS[@]} ]]; do
35
- arg="${ARGS[$i]}"
36
- case "$arg" in
37
- --mode=*)
38
- MODE="${arg#--mode=}"
39
- ;;
40
- --mode|-m)
41
- if [[ $((i+1)) -lt ${#ARGS[@]} ]]; then
42
- ((i++))
43
- MODE="${ARGS[$i]}"
44
- else
45
- echo "Error: --mode requires a value (create, validate, or edit)"
46
- exit 1
47
- fi
48
- ;;
49
- -*)
50
- echo "Error: Unknown option: $arg"
51
- echo "Usage: start-workflow.sh <name> [--mode create|validate|edit]"
52
- exit 1
53
- ;;
54
- *)
55
- if [[ -z "$WORKFLOW_NAME" ]]; then
56
- WORKFLOW_NAME="$arg"
57
- else
58
- echo "Error: Unexpected argument: $arg"
59
- exit 1
60
- fi
61
- ;;
62
- esac
63
- ((i++))
64
- done
65
-
66
- if [[ -z "$WORKFLOW_NAME" ]]; then
67
- echo "# Start Stepped Workflow"
68
- echo ""
69
- echo "Usage: /workflow start <name> [--mode create|validate|edit]"
70
- echo ""
71
- echo "**Available stepped workflows:**"
72
- echo ""
73
- for f in "$WORKFLOWS_DIR"/*.yaml "$WORKFLOWS_DIR"/*/workflow.yaml; do
74
- [[ -f "$f" ]] || continue
75
- workflow_type=$(yq eval '.workflow.type // "phased"' "$f")
76
- if [[ "$workflow_type" == "stepped" ]]; then
77
- name=$(yq eval '.workflow.name' "$f")
78
- desc=$(yq eval '.workflow.description' "$f" | head -1 | cut -c1-60)
79
- echo "- **$name** - $desc"
80
- fi
81
- done
82
- exit 1
83
- fi
84
-
85
- # Find workflow file (support both flat and directory structure)
86
- WORKFLOW_FILE=""
87
- if [[ -f "$WORKFLOWS_DIR/${WORKFLOW_NAME}.yaml" ]]; then
88
- WORKFLOW_FILE="$WORKFLOWS_DIR/${WORKFLOW_NAME}.yaml"
89
- elif [[ -f "$WORKFLOWS_DIR/${WORKFLOW_NAME}/workflow.yaml" ]]; then
90
- WORKFLOW_FILE="$WORKFLOWS_DIR/${WORKFLOW_NAME}/workflow.yaml"
91
- else
92
- echo "Error: Workflow '$WORKFLOW_NAME' not found"
93
- echo ""
94
- echo "Looked in:"
95
- echo " $WORKFLOWS_DIR/${WORKFLOW_NAME}.yaml"
96
- echo " $WORKFLOWS_DIR/${WORKFLOW_NAME}/workflow.yaml"
97
- exit 1
98
- fi
99
-
100
- WORKFLOW_DIR=$(dirname "$WORKFLOW_FILE")
101
-
102
- # Validate it's a stepped workflow
103
- WORKFLOW_TYPE=$(yq eval '.workflow.type // "phased"' "$WORKFLOW_FILE")
104
- if [[ "$WORKFLOW_TYPE" != "stepped" ]]; then
105
- echo "Error: '$WORKFLOW_NAME' is a phased workflow, not stepped"
106
- echo "Use TDD workflow commands (/sm, /tea, /dev, /reviewer) for phased workflows"
107
- exit 1
108
- fi
109
-
110
- # Validate mode if provided
111
- if [[ -n "$MODE" ]]; then
112
- case "$MODE" in
113
- create|validate|edit)
114
- ;;
115
- *)
116
- echo "Error: Invalid mode '$MODE'. Must be one of: create, validate, edit"
117
- exit 1
118
- ;;
119
- esac
120
- fi
121
-
122
- # Get workflow info
123
- WORKFLOW_DESC=$(yq eval '.workflow.description' "$WORKFLOW_FILE")
124
- WORKFLOW_AGENT=$(yq eval '.workflow.agent // "pm"' "$WORKFLOW_FILE")
125
-
126
- # Resolve steps path based on mode
127
- if [[ -n "$MODE" ]]; then
128
- MODE_PATH=$(yq eval ".workflow.modes.$MODE // \"\"" "$WORKFLOW_FILE")
129
- if [[ -z "$MODE_PATH" || "$MODE_PATH" == "null" ]]; then
130
- AVAILABLE_MODES=$(yq eval '.workflow.modes | keys | .[]' "$WORKFLOW_FILE" 2>/dev/null | grep -v default | tr '\n' ', ' | sed 's/,$//')
131
- echo "Error: Mode '$MODE' not available for workflow '$WORKFLOW_NAME'"
132
- echo "Available modes: $AVAILABLE_MODES"
133
- exit 1
134
- fi
135
- STEPS_PATH="$MODE_PATH"
136
- else
137
- # Use default mode or steps.path
138
- DEFAULT_MODE=$(yq eval '.workflow.modes.default // ""' "$WORKFLOW_FILE")
139
- if [[ -n "$DEFAULT_MODE" && "$DEFAULT_MODE" != "null" ]]; then
140
- MODE_PATH=$(yq eval ".workflow.modes.$DEFAULT_MODE // \"\"" "$WORKFLOW_FILE")
141
- if [[ -n "$MODE_PATH" && "$MODE_PATH" != "null" ]]; then
142
- STEPS_PATH="$MODE_PATH"
143
- MODE="$DEFAULT_MODE"
144
- fi
145
- fi
146
-
147
- if [[ -z "${STEPS_PATH:-}" ]]; then
148
- STEPS_PATH=$(yq eval '.workflow.steps.path' "$WORKFLOW_FILE")
149
- MODE="${MODE:-create}"
150
- fi
151
- fi
152
-
153
- # Resolve relative path
154
- if [[ "$STEPS_PATH" == ./* ]]; then
155
- STEPS_PATH="$WORKFLOW_DIR/${STEPS_PATH#./}"
156
- elif [[ "$STEPS_PATH" != /* ]]; then
157
- STEPS_PATH="$PROJECT_ROOT/$STEPS_PATH"
158
- fi
159
-
160
- # Count steps
161
- STEPS_PATTERN=$(yq eval '.workflow.steps.pattern // "step-*.md"' "$WORKFLOW_FILE")
162
- STEP_COUNT=$(find "$STEPS_PATH" -maxdepth 1 -name "step-0*.md" -o -name "step-1*.md" 2>/dev/null | wc -l | tr -d ' ')
163
-
164
- if [[ "$STEP_COUNT" -eq 0 ]]; then
165
- echo "Error: No step files found in $STEPS_PATH"
166
- exit 1
167
- fi
168
-
169
- # Create session directory
170
- mkdir -p "$SESSION_DIR"
171
-
172
- # Generate session filename
173
- SESSION_FILE="$SESSION_DIR/${WORKFLOW_NAME}-workflow-session.md"
174
-
175
- # Check for existing session
176
- if [[ -f "$SESSION_FILE" ]]; then
177
- echo "**Warning:** Existing session found"
178
- echo ""
179
- echo "Session: $SESSION_FILE"
180
- echo ""
181
- echo "Options:"
182
- echo "1. Use \`/workflow resume $WORKFLOW_NAME\` to continue"
183
- echo "2. Delete the session file to start fresh"
184
- echo ""
185
- echo "To start fresh, run:"
186
- echo "\`\`\`bash"
187
- echo "rm \"$SESSION_FILE\""
188
- echo "\`\`\`"
189
- exit 0
190
- fi
191
-
192
- # Create initial session file
193
- NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
194
- cat > "$SESSION_FILE" << EOF
195
- # Workflow Session: $WORKFLOW_NAME
196
-
197
- **Workflow:** $WORKFLOW_NAME
198
- **Type:** stepped
199
- **Agent:** $WORKFLOW_AGENT
200
- **Started:** $NOW
201
-
202
- ## Workflow State
203
- - **Workflow Name:** $WORKFLOW_NAME
204
- - **Type:** stepped
205
- - **Mode:** $MODE
206
- - **Started:** $NOW
207
- - **Last Updated:** $NOW
208
- - **Current Step:** 1
209
- - **Steps Completed:** []
210
- - **Status:** in_progress
211
- - **Notes:** Session created via /workflow start
212
-
213
- ## Progress
214
- - Total Steps: $STEP_COUNT
215
- - Completion: 0%
216
-
217
- ---
218
-
219
- EOF
220
-
221
- # Find step 1 file (handle various naming patterns)
222
- STEP_FILE=$(find "$STEPS_PATH" -maxdepth 1 \( -name "step-01*.md" -o -name "step-1-*.md" \) 2>/dev/null | sort | head -1)
223
-
224
- if [[ -z "$STEP_FILE" ]]; then
225
- echo "Error: Could not find step 1 file in $STEPS_PATH"
226
- exit 1
227
- fi
228
-
229
- # Output workflow start info
230
- echo "# Starting Workflow: $WORKFLOW_NAME"
231
- echo ""
232
- echo "**Description:** $WORKFLOW_DESC"
233
- echo "**Mode:** $MODE"
234
- echo "**Steps:** $STEP_COUNT"
235
- echo "**Agent:** $WORKFLOW_AGENT"
236
- echo "**Session:** $SESSION_FILE"
237
- echo ""
238
-
239
- # Check if auto-handoff is enabled (turbo mode)
240
- CONFIG_FILE="$PROJECT_ROOT/.pennyfarthing/config.local.yaml"
241
- HANDOFF_MODE="manual"
242
- if [[ -f "$CONFIG_FILE" ]]; then
243
- HANDOFF_MODE=$(yq eval '.workflow.handoff_mode // "manual"' "$CONFIG_FILE")
244
- fi
245
-
246
- # Emit Reflector directive - auto-invoke if in turbo mode, else show button
247
- if [[ "$HANDOFF_MODE" == "auto" ]]; then
248
- echo "**Auto-handoff enabled.** Invoking /$WORKFLOW_AGENT agent..."
249
- echo ""
250
- echo "<!-- CYCLIST:INVOKE:/$WORKFLOW_AGENT -->"
251
- else
252
- echo "<!-- CYCLIST:HANDOFF:/$WORKFLOW_AGENT -->"
253
- fi
254
- echo ""
255
- echo "---"
256
- echo ""
257
- echo "## Step 1 of $STEP_COUNT"
258
- echo ""
259
-
260
- # Output step content (strip frontmatter if present)
261
- if head -1 "$STEP_FILE" | grep -q "^---$"; then
262
- awk '/^---$/{if(++c==2){p=1;next}}p' "$STEP_FILE"
263
- else
264
- cat "$STEP_FILE"
265
- fi
266
-
267
- echo ""
268
- echo "---"
269
- echo ""
270
- echo "**Controls:**"
271
- echo "- \`C\` - Continue to next step"
272
- echo "- \`/workflow status\` - Check progress"
273
- echo "- \`/workflow resume\` - Resume after break"