@pennyfarthing/core 10.0.1 → 10.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (492) hide show
  1. package/package.json +13 -3
  2. package/pennyfarthing-dist/agents/README.md +348 -0
  3. package/pennyfarthing-dist/agents/architect.md +180 -0
  4. package/pennyfarthing-dist/agents/dev.md +169 -0
  5. package/pennyfarthing-dist/agents/devops.md +203 -0
  6. package/pennyfarthing-dist/agents/handoff.md +235 -0
  7. package/pennyfarthing-dist/agents/orchestrator.md +182 -0
  8. package/pennyfarthing-dist/agents/pm.md +152 -0
  9. package/pennyfarthing-dist/agents/reviewer-preflight.md +129 -0
  10. package/pennyfarthing-dist/agents/reviewer.md +197 -0
  11. package/pennyfarthing-dist/agents/sm-file-summary.md +79 -0
  12. package/pennyfarthing-dist/agents/sm-finish.md +82 -0
  13. package/pennyfarthing-dist/agents/sm-handoff.md +129 -0
  14. package/pennyfarthing-dist/agents/sm-setup.md +251 -0
  15. package/pennyfarthing-dist/agents/sm.md +298 -0
  16. package/pennyfarthing-dist/agents/tea.md +161 -0
  17. package/pennyfarthing-dist/agents/tech-writer.md +226 -0
  18. package/pennyfarthing-dist/agents/testing-runner.md +184 -0
  19. package/pennyfarthing-dist/agents/ux-designer.md +236 -0
  20. package/pennyfarthing-dist/agents/workflow-status-check.md +96 -0
  21. package/pennyfarthing-dist/commands/architect.md +9 -0
  22. package/pennyfarthing-dist/commands/benchmark-control.md +69 -0
  23. package/pennyfarthing-dist/commands/benchmark.md +485 -0
  24. package/pennyfarthing-dist/commands/brainstorming.md +91 -0
  25. package/pennyfarthing-dist/commands/check.md +156 -0
  26. package/pennyfarthing-dist/commands/chore.md +218 -0
  27. package/pennyfarthing-dist/commands/close-epic.md +139 -0
  28. package/pennyfarthing-dist/commands/continue-session.md +218 -0
  29. package/pennyfarthing-dist/commands/create-branches-from-story.md +358 -0
  30. package/pennyfarthing-dist/commands/create-theme.md +29 -0
  31. package/pennyfarthing-dist/commands/dev.md +9 -0
  32. package/pennyfarthing-dist/commands/devops.md +9 -0
  33. package/pennyfarthing-dist/commands/fix-blocker.md +22 -0
  34. package/pennyfarthing-dist/commands/git-cleanup.md +57 -0
  35. package/pennyfarthing-dist/commands/health-check.md +143 -0
  36. package/pennyfarthing-dist/commands/help.md +264 -0
  37. package/pennyfarthing-dist/commands/job-fair.md +102 -0
  38. package/pennyfarthing-dist/commands/list-themes.md +21 -0
  39. package/pennyfarthing-dist/commands/new-work.md +23 -0
  40. package/pennyfarthing-dist/commands/orchestrator.md +9 -0
  41. package/pennyfarthing-dist/commands/parallel-work.md +73 -0
  42. package/pennyfarthing-dist/commands/party-mode.md +77 -0
  43. package/pennyfarthing-dist/commands/patch.md +210 -0
  44. package/pennyfarthing-dist/commands/permissions.md +193 -0
  45. package/pennyfarthing-dist/commands/pm.md +9 -0
  46. package/pennyfarthing-dist/commands/prime.md +136 -0
  47. package/pennyfarthing-dist/commands/release.md +74 -0
  48. package/pennyfarthing-dist/commands/repo-status.md +49 -0
  49. package/pennyfarthing-dist/commands/retro.md +200 -0
  50. package/pennyfarthing-dist/commands/reviewer.md +9 -0
  51. package/pennyfarthing-dist/commands/run-ci.md +116 -0
  52. package/pennyfarthing-dist/commands/set-theme.md +56 -0
  53. package/pennyfarthing-dist/commands/setup.md +65 -0
  54. package/pennyfarthing-dist/commands/show-theme.md +21 -0
  55. package/pennyfarthing-dist/commands/sm.md +9 -0
  56. package/pennyfarthing-dist/commands/solo.md +447 -0
  57. package/pennyfarthing-dist/commands/sprint-planning.md +109 -0
  58. package/pennyfarthing-dist/commands/sprint.md +142 -0
  59. package/pennyfarthing-dist/commands/standalone.md +194 -0
  60. package/pennyfarthing-dist/commands/start-epic.md +168 -0
  61. package/pennyfarthing-dist/commands/sync-epic-to-jira.md +184 -0
  62. package/pennyfarthing-dist/commands/sync-work-with-sprint.md +373 -0
  63. package/pennyfarthing-dist/commands/tea.md +9 -0
  64. package/pennyfarthing-dist/commands/tech-writer.md +9 -0
  65. package/pennyfarthing-dist/commands/theme-maker.md +676 -0
  66. package/pennyfarthing-dist/commands/update-domain-docs.md +83 -0
  67. package/pennyfarthing-dist/commands/ux-designer.md +9 -0
  68. package/pennyfarthing-dist/commands/work.md +25 -0
  69. package/pennyfarthing-dist/commands/workflow.md +21 -0
  70. package/pennyfarthing-dist/guides/agent-behavior.md +92 -0
  71. package/pennyfarthing-dist/guides/agent-coordination.md +475 -0
  72. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +432 -0
  73. package/pennyfarthing-dist/guides/agent-template-strategic.md +148 -0
  74. package/pennyfarthing-dist/guides/agent-template-tactical.md +162 -0
  75. package/pennyfarthing-dist/guides/hooks.md +230 -0
  76. package/pennyfarthing-dist/guides/measurement-framework.md +210 -0
  77. package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +766 -0
  78. package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +574 -0
  79. package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +488 -0
  80. package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +402 -0
  81. package/pennyfarthing-dist/guides/permission-protocol.md +188 -0
  82. package/pennyfarthing-dist/guides/persona-loading.md +46 -0
  83. package/pennyfarthing-dist/guides/prompt-patterns.md +338 -0
  84. package/pennyfarthing-dist/guides/scale-levels.md +114 -0
  85. package/pennyfarthing-dist/guides/session-artifacts.md +193 -0
  86. package/pennyfarthing-dist/guides/session-schema.md +346 -0
  87. package/pennyfarthing-dist/guides/skill-schema.md +412 -0
  88. package/pennyfarthing-dist/guides/workflow-schema.md +257 -0
  89. package/pennyfarthing-dist/guides/workflow-step-schema.md +512 -0
  90. package/pennyfarthing-dist/guides/worktree-mode.md +113 -0
  91. package/pennyfarthing-dist/guides/xml-tags.md +627 -0
  92. package/pennyfarthing-dist/output-styles/teaching.md +33 -0
  93. package/pennyfarthing-dist/output-styles/terse.md +20 -0
  94. package/pennyfarthing-dist/output-styles/verbose.md +28 -0
  95. package/pennyfarthing-dist/personas/themes/a-team.yaml +331 -0
  96. package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +324 -0
  97. package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +282 -0
  98. package/pennyfarthing-dist/personas/themes/blade-runner.yaml +289 -0
  99. package/pennyfarthing-dist/personas/themes/catch-22.yaml +304 -0
  100. package/pennyfarthing-dist/personas/themes/control.yaml +201 -0
  101. package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +315 -0
  102. package/pennyfarthing-dist/personas/themes/discworld.yaml +334 -0
  103. package/pennyfarthing-dist/personas/themes/doctor-who.yaml +284 -0
  104. package/pennyfarthing-dist/personas/themes/dune.yaml +301 -0
  105. package/pennyfarthing-dist/personas/themes/firefly.yaml +320 -0
  106. package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +284 -0
  107. package/pennyfarthing-dist/personas/themes/harry-potter.yaml +316 -0
  108. package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +323 -0
  109. package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +326 -0
  110. package/pennyfarthing-dist/personas/themes/mad-max.yaml +349 -0
  111. package/pennyfarthing-dist/personas/themes/mash.yaml +329 -0
  112. package/pennyfarthing-dist/personas/themes/princess-bride.yaml +344 -0
  113. package/pennyfarthing-dist/personas/themes/sandman.yaml +282 -0
  114. package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +358 -0
  115. package/pennyfarthing-dist/personas/themes/star-wars.yaml +297 -0
  116. package/pennyfarthing-dist/personas/themes/the-expanse.yaml +337 -0
  117. package/pennyfarthing-dist/personas/themes/the-matrix.yaml +342 -0
  118. package/pennyfarthing-dist/personas/themes/watchmen.yaml +285 -0
  119. package/pennyfarthing-dist/personas/themes/west-wing.yaml +285 -0
  120. package/pennyfarthing-dist/personas/themes/x-files.yaml +296 -0
  121. package/pennyfarthing-dist/scripts/README.md +87 -0
  122. package/pennyfarthing-dist/scripts/core/README.md +25 -0
  123. package/pennyfarthing-dist/scripts/core/agent-session.sh +390 -0
  124. package/pennyfarthing-dist/scripts/core/check-context.sh +194 -0
  125. package/pennyfarthing-dist/scripts/core/handoff-marker.sh +112 -0
  126. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +90 -0
  127. package/pennyfarthing-dist/scripts/core/prime.sh +30 -0
  128. package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +21 -0
  129. package/pennyfarthing-dist/scripts/git/README.md +25 -0
  130. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +267 -0
  131. package/pennyfarthing-dist/scripts/git/git-status-all.sh +152 -0
  132. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +79 -0
  133. package/pennyfarthing-dist/scripts/git/release.sh +246 -0
  134. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +497 -0
  135. package/pennyfarthing-dist/scripts/health/drift-detection.sh +156 -0
  136. package/pennyfarthing-dist/scripts/hooks/README.md +32 -0
  137. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  138. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +106 -0
  139. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +95 -0
  140. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +65 -0
  141. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +35 -0
  142. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +150 -0
  143. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +190 -0
  144. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +71 -0
  145. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +42 -0
  146. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +20 -0
  147. package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +499 -0
  148. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +30 -0
  149. package/pennyfarthing-dist/scripts/hooks/session-start.sh +97 -0
  150. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +65 -0
  151. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +78 -0
  152. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +94 -0
  153. package/pennyfarthing-dist/scripts/jira/README.md +36 -0
  154. package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +95 -0
  155. package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +91 -0
  156. package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +22 -0
  157. package/pennyfarthing-dist/scripts/jira/jira-lib.sh +464 -0
  158. package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +260 -0
  159. package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +18 -0
  160. package/pennyfarthing-dist/scripts/jira/jira-sync.sh +16 -0
  161. package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +16 -0
  162. package/pennyfarthing-dist/scripts/jira/sync-epic-to-jira.sh +16 -0
  163. package/pennyfarthing-dist/scripts/lib/README.md +29 -0
  164. package/pennyfarthing-dist/scripts/lib/background-tasks.sh +177 -0
  165. package/pennyfarthing-dist/scripts/lib/checkpoint.sh +136 -0
  166. package/pennyfarthing-dist/scripts/lib/common.sh +212 -0
  167. package/pennyfarthing-dist/scripts/lib/file-lock.sh +269 -0
  168. package/pennyfarthing-dist/scripts/lib/find-root.sh +58 -0
  169. package/pennyfarthing-dist/scripts/lib/logging.sh +186 -0
  170. package/pennyfarthing-dist/scripts/lib/retry.sh +76 -0
  171. package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +102 -0
  172. package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +91 -0
  173. package/pennyfarthing-dist/scripts/misc/README.md +44 -0
  174. package/pennyfarthing-dist/scripts/misc/add-short-names.sh +13 -0
  175. package/pennyfarthing-dist/scripts/misc/add_short_names.py +226 -0
  176. package/pennyfarthing-dist/scripts/misc/backlog.sh +77 -0
  177. package/pennyfarthing-dist/scripts/misc/check-status.sh +247 -0
  178. package/pennyfarthing-dist/scripts/misc/find-related-work.sh +231 -0
  179. package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +107 -0
  180. package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +74 -0
  181. package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +10 -0
  182. package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +319 -0
  183. package/pennyfarthing-dist/scripts/misc/repo-scan.sh +141 -0
  184. package/pennyfarthing-dist/scripts/misc/repo-utils.sh +778 -0
  185. package/pennyfarthing-dist/scripts/misc/run-ci.sh +212 -0
  186. package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +7 -0
  187. package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +319 -0
  188. package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +193 -0
  189. package/pennyfarthing-dist/scripts/misc/statusline.sh +257 -0
  190. package/pennyfarthing-dist/scripts/misc/uninstall.sh +275 -0
  191. package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +160 -0
  192. package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +417 -0
  193. package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +54 -0
  194. package/pennyfarthing-dist/scripts/sprint/README.md +29 -0
  195. package/pennyfarthing-dist/scripts/sprint/archive-story.sh +133 -0
  196. package/pennyfarthing-dist/scripts/sprint/available-stories.sh +91 -0
  197. package/pennyfarthing-dist/scripts/sprint/check-story.sh +158 -0
  198. package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +52 -0
  199. package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +63 -0
  200. package/pennyfarthing-dist/scripts/sprint/list-future.sh +145 -0
  201. package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +110 -0
  202. package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +148 -0
  203. package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +415 -0
  204. package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +33 -0
  205. package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +230 -0
  206. package/pennyfarthing-dist/scripts/sprint/sprint-status.sh +134 -0
  207. package/pennyfarthing-dist/scripts/sprint/validate-sprint-yaml.sh +139 -0
  208. package/pennyfarthing-dist/scripts/story/README.md +23 -0
  209. package/pennyfarthing-dist/scripts/story/create-story.sh +19 -0
  210. package/pennyfarthing-dist/scripts/story/size-story.sh +18 -0
  211. package/pennyfarthing-dist/scripts/story/story-template.sh +18 -0
  212. package/pennyfarthing-dist/scripts/test/README.md +23 -0
  213. package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +59 -0
  214. package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +220 -0
  215. package/pennyfarthing-dist/scripts/test/swebench-judge.py +374 -0
  216. package/pennyfarthing-dist/scripts/test/test-cache.sh +165 -0
  217. package/pennyfarthing-dist/scripts/test/test-setup.sh +337 -0
  218. package/pennyfarthing-dist/scripts/tests/check.test.sh +582 -0
  219. package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +515 -0
  220. package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +599 -0
  221. package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +332 -0
  222. package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +573 -0
  223. package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +859 -0
  224. package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +662 -0
  225. package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +589 -0
  226. package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +106 -0
  227. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +597 -0
  228. package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +514 -0
  229. package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +517 -0
  230. package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +331 -0
  231. package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +647 -0
  232. package/pennyfarthing-dist/scripts/theme/README.md +22 -0
  233. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +13 -0
  234. package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +402 -0
  235. package/pennyfarthing-dist/scripts/theme/list-themes.sh +30 -0
  236. package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +97 -0
  237. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +576 -0
  238. package/pennyfarthing-dist/scripts/workflow/README.md +28 -0
  239. package/pennyfarthing-dist/scripts/workflow/check.py +502 -0
  240. package/pennyfarthing-dist/scripts/workflow/check.sh +24 -0
  241. package/pennyfarthing-dist/scripts/workflow/complete-step.py +304 -0
  242. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +154 -0
  243. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +222 -0
  244. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +61 -0
  245. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +13 -0
  246. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +124 -0
  247. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +34 -0
  248. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +157 -0
  249. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +132 -0
  250. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +250 -0
  251. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +161 -0
  252. package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +246 -0
  253. package/pennyfarthing-dist/skills/changelog/SKILL.md +385 -0
  254. package/pennyfarthing-dist/skills/code-review/SKILL.md +172 -0
  255. package/pennyfarthing-dist/skills/context-engineering/SKILL.md +277 -0
  256. package/pennyfarthing-dist/skills/cyclist/SKILL.md +88 -0
  257. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +461 -0
  258. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +261 -0
  259. package/pennyfarthing-dist/skills/jira/SKILL.md +508 -0
  260. package/pennyfarthing-dist/skills/judge/SKILL.md +644 -0
  261. package/pennyfarthing-dist/skills/just/SKILL.md +414 -0
  262. package/pennyfarthing-dist/skills/mermaid/SKILL.md +256 -0
  263. package/pennyfarthing-dist/skills/otel/skill.md +227 -0
  264. package/pennyfarthing-dist/skills/permissions/skill.md +157 -0
  265. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +187 -0
  266. package/pennyfarthing-dist/skills/skill-registry.schema.json +107 -0
  267. package/pennyfarthing-dist/skills/skill-registry.yaml +393 -0
  268. package/pennyfarthing-dist/skills/sprint/scripts/archive-story.sh +101 -0
  269. package/pennyfarthing-dist/skills/sprint/scripts/available-stories.sh +97 -0
  270. package/pennyfarthing-dist/skills/sprint/scripts/check-story.sh +164 -0
  271. package/pennyfarthing-dist/skills/sprint/scripts/create-jira-epic.sh +101 -0
  272. package/pennyfarthing-dist/skills/sprint/scripts/new-sprint.sh +116 -0
  273. package/pennyfarthing-dist/skills/sprint/scripts/promote-epic.sh +164 -0
  274. package/pennyfarthing-dist/skills/sprint/scripts/sprint-info.sh +39 -0
  275. package/pennyfarthing-dist/skills/sprint/scripts/sprint-status.sh +147 -0
  276. package/pennyfarthing-dist/skills/sprint/scripts/sync-epic-jira.sh +93 -0
  277. package/pennyfarthing-dist/skills/sprint/skill.md +465 -0
  278. package/pennyfarthing-dist/skills/story/scripts/create-story.sh +159 -0
  279. package/pennyfarthing-dist/skills/story/scripts/size-story.sh +198 -0
  280. package/pennyfarthing-dist/skills/story/scripts/story-template.sh +162 -0
  281. package/pennyfarthing-dist/skills/story/skill.md +219 -0
  282. package/pennyfarthing-dist/skills/systematic-debugging/SKILL.md +446 -0
  283. package/pennyfarthing-dist/skills/testing/SKILL.md +121 -0
  284. package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +124 -0
  285. package/pennyfarthing-dist/skills/theme/skill.md +141 -0
  286. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +178 -0
  287. package/pennyfarthing-dist/skills/workflow/scripts/list-workflows.sh +91 -0
  288. package/pennyfarthing-dist/skills/workflow/scripts/resume-workflow.sh +163 -0
  289. package/pennyfarthing-dist/skills/workflow/scripts/show-workflow.sh +138 -0
  290. package/pennyfarthing-dist/skills/workflow/scripts/start-workflow.sh +273 -0
  291. package/pennyfarthing-dist/skills/workflow/scripts/workflow-status.sh +167 -0
  292. package/pennyfarthing-dist/skills/workflow/skill.md +345 -0
  293. package/pennyfarthing-dist/skills/yq/SKILL.md +272 -0
  294. package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +187 -0
  295. package/pennyfarthing-dist/templates/LEADERBOARD.template.md +59 -0
  296. package/pennyfarthing-dist/templates/agent-scopes.yaml.template +276 -0
  297. package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +61 -0
  298. package/pennyfarthing-dist/templates/persona-config.yaml.template +22 -0
  299. package/pennyfarthing-dist/templates/preferences.yaml.template +15 -0
  300. package/pennyfarthing-dist/templates/settings.local.json.template +130 -0
  301. package/pennyfarthing-dist/templates/setup-env.sh.template +18 -0
  302. package/pennyfarthing-dist/templates/shared-context.md.template +70 -0
  303. package/pennyfarthing-dist/templates/sidecar/decisions.md.template +40 -0
  304. package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +37 -0
  305. package/pennyfarthing-dist/templates/sidecar/patterns.md.template +34 -0
  306. package/pennyfarthing-dist/workflows/agent-docs.yaml +70 -0
  307. package/pennyfarthing-dist/workflows/architecture/steps/step-01-initialize.md +113 -0
  308. package/pennyfarthing-dist/workflows/architecture/steps/step-01b-continue.md +105 -0
  309. package/pennyfarthing-dist/workflows/architecture/steps/step-02-context.md +127 -0
  310. package/pennyfarthing-dist/workflows/architecture/steps/step-03-patterns.md +145 -0
  311. package/pennyfarthing-dist/workflows/architecture/steps/step-04-components.md +150 -0
  312. package/pennyfarthing-dist/workflows/architecture/steps/step-05-interfaces.md +145 -0
  313. package/pennyfarthing-dist/workflows/architecture/steps/step-06-risks.md +154 -0
  314. package/pennyfarthing-dist/workflows/architecture/steps/step-07-document.md +172 -0
  315. package/pennyfarthing-dist/workflows/architecture/templates/architecture-decision.md +102 -0
  316. package/pennyfarthing-dist/workflows/architecture.yaml +65 -0
  317. package/pennyfarthing-dist/workflows/bdd.yaml +60 -0
  318. package/pennyfarthing-dist/workflows/brainstorming/brain-methods.csv +62 -0
  319. package/pennyfarthing-dist/workflows/brainstorming/checklist.md +44 -0
  320. package/pennyfarthing-dist/workflows/brainstorming/instructions.md +736 -0
  321. package/pennyfarthing-dist/workflows/brainstorming/workflow.yaml +49 -0
  322. package/pennyfarthing-dist/workflows/code-review/checklist.md +23 -0
  323. package/pennyfarthing-dist/workflows/code-review/instructions.md +234 -0
  324. package/pennyfarthing-dist/workflows/code-review/workflow.yaml +51 -0
  325. package/pennyfarthing-dist/workflows/dev-story/checklist.md +80 -0
  326. package/pennyfarthing-dist/workflows/dev-story/instructions.xml +410 -0
  327. package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +50 -0
  328. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-01-validate-prerequisites.md +281 -0
  329. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-02-design-epics.md +256 -0
  330. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-03-create-stories.md +298 -0
  331. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +177 -0
  332. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +145 -0
  333. package/pennyfarthing-dist/workflows/epics-and-stories/templates/epics-template.md +57 -0
  334. package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +28 -0
  335. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +103 -0
  336. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-02-categorize.md +147 -0
  337. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +215 -0
  338. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +97 -0
  339. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +78 -0
  340. package/pennyfarthing-dist/workflows/git-cleanup.yaml +59 -0
  341. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-01-document-discovery.md +211 -0
  342. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-02-prd-analysis.md +199 -0
  343. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-03-epic-coverage-validation.md +202 -0
  344. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-04-ux-alignment.md +162 -0
  345. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-05-epic-quality-review.md +280 -0
  346. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-06-final-assessment.md +158 -0
  347. package/pennyfarthing-dist/workflows/implementation-readiness/templates/readiness-report-template.md +4 -0
  348. package/pennyfarthing-dist/workflows/implementation-readiness/workflow.yaml +40 -0
  349. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-01-connect.md +257 -0
  350. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-02-explore.md +107 -0
  351. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-03-fix.md +127 -0
  352. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-04-commit.md +122 -0
  353. package/pennyfarthing-dist/workflows/interactive-debug/workflow.yaml +51 -0
  354. package/pennyfarthing-dist/workflows/patch.yaml +67 -0
  355. package/pennyfarthing-dist/workflows/prd/data/domain-complexity.csv +13 -0
  356. package/pennyfarthing-dist/workflows/prd/data/prd-purpose.md +197 -0
  357. package/pennyfarthing-dist/workflows/prd/data/project-types.csv +11 -0
  358. package/pennyfarthing-dist/workflows/prd/steps-c/step-01-init.md +197 -0
  359. package/pennyfarthing-dist/workflows/prd/steps-c/step-01b-continue.md +159 -0
  360. package/pennyfarthing-dist/workflows/prd/steps-c/step-02-discovery.md +230 -0
  361. package/pennyfarthing-dist/workflows/prd/steps-c/step-03-success.md +232 -0
  362. package/pennyfarthing-dist/workflows/prd/steps-c/step-04-journeys.md +219 -0
  363. package/pennyfarthing-dist/workflows/prd/steps-c/step-05-domain.md +213 -0
  364. package/pennyfarthing-dist/workflows/prd/steps-c/step-06-innovation.md +232 -0
  365. package/pennyfarthing-dist/workflows/prd/steps-c/step-07-project-type.md +243 -0
  366. package/pennyfarthing-dist/workflows/prd/steps-c/step-08-scoping.md +234 -0
  367. package/pennyfarthing-dist/workflows/prd/steps-c/step-09-functional.md +237 -0
  368. package/pennyfarthing-dist/workflows/prd/steps-c/step-10-nonfunctional.md +248 -0
  369. package/pennyfarthing-dist/workflows/prd/steps-c/step-11-polish.md +223 -0
  370. package/pennyfarthing-dist/workflows/prd/steps-c/step-12-complete.md +186 -0
  371. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01-discovery.md +253 -0
  372. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01b-legacy-conversion.md +214 -0
  373. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-02-review.md +255 -0
  374. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-03-edit.md +259 -0
  375. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-04-complete.md +174 -0
  376. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-01-discovery.md +224 -0
  377. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02-format-detection.md +197 -0
  378. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02b-parity-check.md +215 -0
  379. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-03-density-validation.md +180 -0
  380. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +220 -0
  381. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-05-measurability-validation.md +234 -0
  382. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-06-traceability-validation.md +223 -0
  383. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +211 -0
  384. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +249 -0
  385. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-09-project-type-validation.md +269 -0
  386. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-10-smart-validation.md +215 -0
  387. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +270 -0
  388. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-12-completeness-validation.md +248 -0
  389. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-13-report-complete.md +238 -0
  390. package/pennyfarthing-dist/workflows/prd/templates/prd-template.md +10 -0
  391. package/pennyfarthing-dist/workflows/prd/workflow.yaml +42 -0
  392. package/pennyfarthing-dist/workflows/product-brief/steps/step-01-init.md +195 -0
  393. package/pennyfarthing-dist/workflows/product-brief/steps/step-01b-continue.md +180 -0
  394. package/pennyfarthing-dist/workflows/product-brief/steps/step-02-vision.md +221 -0
  395. package/pennyfarthing-dist/workflows/product-brief/steps/step-03-users.md +224 -0
  396. package/pennyfarthing-dist/workflows/product-brief/steps/step-04-metrics.md +228 -0
  397. package/pennyfarthing-dist/workflows/product-brief/steps/step-05-scope.md +243 -0
  398. package/pennyfarthing-dist/workflows/product-brief/steps/step-06-complete.md +216 -0
  399. package/pennyfarthing-dist/workflows/product-brief/templates/product-brief.template.md +10 -0
  400. package/pennyfarthing-dist/workflows/product-brief/workflow.yaml +31 -0
  401. package/pennyfarthing-dist/workflows/project-context/project-context-template.md +21 -0
  402. package/pennyfarthing-dist/workflows/project-context/steps/step-01-discover.md +206 -0
  403. package/pennyfarthing-dist/workflows/project-context/steps/step-02-generate.md +349 -0
  404. package/pennyfarthing-dist/workflows/project-context/steps/step-03-complete.md +306 -0
  405. package/pennyfarthing-dist/workflows/project-context/workflow.yaml +27 -0
  406. package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +157 -0
  407. package/pennyfarthing-dist/workflows/project-setup/steps/step-02-clone-repos.md +217 -0
  408. package/pennyfarthing-dist/workflows/project-setup/steps/step-03-repos-yaml.md +159 -0
  409. package/pennyfarthing-dist/workflows/project-setup/steps/step-04-claude-md.md +186 -0
  410. package/pennyfarthing-dist/workflows/project-setup/steps/step-05-shared-context.md +185 -0
  411. package/pennyfarthing-dist/workflows/project-setup/steps/step-06-task-runner.md +279 -0
  412. package/pennyfarthing-dist/workflows/project-setup/steps/step-07-theme.md +200 -0
  413. package/pennyfarthing-dist/workflows/project-setup/steps/step-08-theme-packs.md +142 -0
  414. package/pennyfarthing-dist/workflows/project-setup/steps/step-09-cyclist.md +245 -0
  415. package/pennyfarthing-dist/workflows/project-setup/steps/step-10-complete.md +204 -0
  416. package/pennyfarthing-dist/workflows/project-setup/workflow.yaml +41 -0
  417. package/pennyfarthing-dist/workflows/quick-dev/steps/step-01-mode-detection.md +177 -0
  418. package/pennyfarthing-dist/workflows/quick-dev/steps/step-02-context-gathering.md +143 -0
  419. package/pennyfarthing-dist/workflows/quick-dev/steps/step-03-execute.md +138 -0
  420. package/pennyfarthing-dist/workflows/quick-dev/steps/step-04-self-check.md +135 -0
  421. package/pennyfarthing-dist/workflows/quick-dev/steps/step-05-adversarial-review.md +129 -0
  422. package/pennyfarthing-dist/workflows/quick-dev/steps/step-06-resolve-findings.md +163 -0
  423. package/pennyfarthing-dist/workflows/quick-dev/workflow.yaml +27 -0
  424. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +201 -0
  425. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +156 -0
  426. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +140 -0
  427. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +203 -0
  428. package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +74 -0
  429. package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +27 -0
  430. package/pennyfarthing-dist/workflows/release/steps/step-01-preflight.md +105 -0
  431. package/pennyfarthing-dist/workflows/release/steps/step-02-bump.md +95 -0
  432. package/pennyfarthing-dist/workflows/release/steps/step-03-changelog.md +125 -0
  433. package/pennyfarthing-dist/workflows/release/steps/step-04-readme.md +101 -0
  434. package/pennyfarthing-dist/workflows/release/steps/step-05-claude-md.md +102 -0
  435. package/pennyfarthing-dist/workflows/release/steps/step-06-retro.md +59 -0
  436. package/pennyfarthing-dist/workflows/release/steps/step-07-commit.md +109 -0
  437. package/pennyfarthing-dist/workflows/release/steps/step-08-merge.md +65 -0
  438. package/pennyfarthing-dist/workflows/release/steps/step-09-push.md +75 -0
  439. package/pennyfarthing-dist/workflows/release/steps/step-10-publish.md +93 -0
  440. package/pennyfarthing-dist/workflows/release/steps/step-11-finalize.md +71 -0
  441. package/pennyfarthing-dist/workflows/release.yaml +62 -0
  442. package/pennyfarthing-dist/workflows/research/steps-domain/step-01-init.md +159 -0
  443. package/pennyfarthing-dist/workflows/research/steps-domain/step-02-domain-analysis.md +253 -0
  444. package/pennyfarthing-dist/workflows/research/steps-domain/step-03-competitive-landscape.md +263 -0
  445. package/pennyfarthing-dist/workflows/research/steps-domain/step-04-regulatory-focus.md +232 -0
  446. package/pennyfarthing-dist/workflows/research/steps-domain/step-05-technical-trends.md +260 -0
  447. package/pennyfarthing-dist/workflows/research/steps-domain/step-06-research-synthesis.md +477 -0
  448. package/pennyfarthing-dist/workflows/research/steps-market/step-01-init.md +205 -0
  449. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-behavior.md +262 -0
  450. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-insights.md +227 -0
  451. package/pennyfarthing-dist/workflows/research/steps-market/step-03-customer-pain-points.md +275 -0
  452. package/pennyfarthing-dist/workflows/research/steps-market/step-04-customer-decisions.md +286 -0
  453. package/pennyfarthing-dist/workflows/research/steps-market/step-05-competitive-analysis.md +203 -0
  454. package/pennyfarthing-dist/workflows/research/steps-market/step-06-research-completion.md +510 -0
  455. package/pennyfarthing-dist/workflows/research/steps-technical/step-01-init.md +159 -0
  456. package/pennyfarthing-dist/workflows/research/steps-technical/step-02-technical-overview.md +264 -0
  457. package/pennyfarthing-dist/workflows/research/steps-technical/step-03-integration-patterns.md +274 -0
  458. package/pennyfarthing-dist/workflows/research/steps-technical/step-04-architectural-patterns.md +228 -0
  459. package/pennyfarthing-dist/workflows/research/steps-technical/step-05-implementation-research.md +267 -0
  460. package/pennyfarthing-dist/workflows/research/steps-technical/step-06-research-synthesis.md +522 -0
  461. package/pennyfarthing-dist/workflows/research/templates/research.template.md +29 -0
  462. package/pennyfarthing-dist/workflows/research/workflow.yaml +45 -0
  463. package/pennyfarthing-dist/workflows/retrospective/checklist.md +31 -0
  464. package/pennyfarthing-dist/workflows/retrospective/instructions.md +1443 -0
  465. package/pennyfarthing-dist/workflows/retrospective/workflow.yaml +50 -0
  466. package/pennyfarthing-dist/workflows/sprint-planning/checklist.md +33 -0
  467. package/pennyfarthing-dist/workflows/sprint-planning/sprint-status-template.yaml +55 -0
  468. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-01-parse-epic-files.md +69 -0
  469. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-02-build-sprint-status.md +61 -0
  470. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-03-status-detection.md +80 -0
  471. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-04-generate-status-file.md +90 -0
  472. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-05-validate-and-report.md +78 -0
  473. package/pennyfarthing-dist/workflows/sprint-planning/workflow.yaml +34 -0
  474. package/pennyfarthing-dist/workflows/tdd.yaml +50 -0
  475. package/pennyfarthing-dist/workflows/trivial.yaml +40 -0
  476. package/pennyfarthing-dist/workflows/ux-design/steps/step-01-init.md +141 -0
  477. package/pennyfarthing-dist/workflows/ux-design/steps/step-01b-continue.md +133 -0
  478. package/pennyfarthing-dist/workflows/ux-design/steps/step-02-discovery.md +196 -0
  479. package/pennyfarthing-dist/workflows/ux-design/steps/step-03-core-experience.md +222 -0
  480. package/pennyfarthing-dist/workflows/ux-design/steps/step-04-emotional-response.md +225 -0
  481. package/pennyfarthing-dist/workflows/ux-design/steps/step-05-inspiration.md +240 -0
  482. package/pennyfarthing-dist/workflows/ux-design/steps/step-06-design-system.md +258 -0
  483. package/pennyfarthing-dist/workflows/ux-design/steps/step-07-defining-experience.md +260 -0
  484. package/pennyfarthing-dist/workflows/ux-design/steps/step-08-visual-foundation.md +230 -0
  485. package/pennyfarthing-dist/workflows/ux-design/steps/step-09-design-directions.md +230 -0
  486. package/pennyfarthing-dist/workflows/ux-design/steps/step-10-user-journeys.md +247 -0
  487. package/pennyfarthing-dist/workflows/ux-design/steps/step-11-component-strategy.md +254 -0
  488. package/pennyfarthing-dist/workflows/ux-design/steps/step-12-ux-patterns.md +243 -0
  489. package/pennyfarthing-dist/workflows/ux-design/steps/step-13-responsive-accessibility.md +270 -0
  490. package/pennyfarthing-dist/workflows/ux-design/steps/step-14-complete.md +234 -0
  491. package/pennyfarthing-dist/workflows/ux-design/ux-design-template.md +13 -0
  492. package/pennyfarthing-dist/workflows/ux-design/workflow.yaml +41 -0
@@ -0,0 +1,304 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ complete-step.py - Complete the current step of a stepped workflow
4
+
5
+ Usage: python complete-step.py [name] [--step N]
6
+
7
+ Advances session state: increments current step, updates steps completed,
8
+ recalculates completion percentage, and marks workflow as completed when
9
+ all steps are done.
10
+
11
+ If no name provided, detects from active session.
12
+ If --step N provided, completes that specific step instead of current step.
13
+ """
14
+
15
+ import argparse
16
+ import re
17
+ import sys
18
+ from datetime import datetime, timezone
19
+ from pathlib import Path
20
+
21
+ try:
22
+ import yaml
23
+ except ImportError:
24
+ print("Error: PyYAML required. Install with: pip install pyyaml", file=sys.stderr)
25
+ sys.exit(1)
26
+
27
+
28
+ def find_project_root() -> Path:
29
+ """Find project root by looking for .pennyfarthing directory."""
30
+ # Honor explicit PROJECT_ROOT override
31
+ import os
32
+ override = os.environ.get("PROJECT_ROOT")
33
+ if override:
34
+ return Path(override)
35
+
36
+ current = Path.cwd()
37
+ while current != current.parent:
38
+ if (current / ".pennyfarthing").is_dir():
39
+ return current
40
+ current = current.parent
41
+ print("Error: Could not find .pennyfarthing/ directory", file=sys.stderr)
42
+ print("Are you in a Pennyfarthing-enabled project?", file=sys.stderr)
43
+ sys.exit(1)
44
+
45
+
46
+ def parse_session_field(content: str, field: str) -> str:
47
+ """Extract a field value from session markdown."""
48
+ pattern = rf"^- \*\*{re.escape(field)}:\*\*\s*(.+)$"
49
+ match = re.search(pattern, content, re.MULTILINE)
50
+ return match.group(1).strip() if match else ""
51
+
52
+
53
+ def find_session_file(session_dir: Path, workflow_name: str | None) -> tuple[Path, str]:
54
+ """Find session file and determine workflow name.
55
+
56
+ Returns (session_path, workflow_name).
57
+ """
58
+ if workflow_name:
59
+ session_file = session_dir / f"{workflow_name}-workflow-session.md"
60
+ if not session_file.exists():
61
+ print(f"Error: No session found for workflow '{workflow_name}'", file=sys.stderr)
62
+ print(f"\nUse `/workflow start {workflow_name}` to begin.", file=sys.stderr)
63
+ sys.exit(1)
64
+ return session_file, workflow_name
65
+
66
+ # Auto-detect from session directory
67
+ sessions = list(session_dir.glob("*-workflow-session.md"))
68
+ if not sessions:
69
+ print("Error: No active workflow session found.", file=sys.stderr)
70
+ print("\nUsage: complete-step.py [name] [--step N]", file=sys.stderr)
71
+ sys.exit(1)
72
+
73
+ session_file = sorted(sessions)[0]
74
+ content = session_file.read_text()
75
+
76
+ # Try to extract workflow name from content
77
+ wf_match = re.search(r"^\*\*Workflow:\*\*\s*(.+)$", content, re.MULTILINE)
78
+ if wf_match:
79
+ name = wf_match.group(1).strip()
80
+ else:
81
+ # Derive from filename
82
+ name = session_file.stem.replace("-workflow-session", "")
83
+
84
+ return session_file, name
85
+
86
+
87
+ def find_workflow_file(workflows_dir: Path, workflow_name: str) -> Path:
88
+ """Find workflow YAML definition."""
89
+ flat = workflows_dir / f"{workflow_name}.yaml"
90
+ if flat.exists():
91
+ return flat
92
+
93
+ nested = workflows_dir / workflow_name / "workflow.yaml"
94
+ if nested.exists():
95
+ return nested
96
+
97
+ print(f"Error: Workflow definition '{workflow_name}' not found", file=sys.stderr)
98
+ sys.exit(1)
99
+
100
+
101
+ def count_steps(steps_path: Path) -> int:
102
+ """Count step files in a directory."""
103
+ return len([
104
+ f for f in steps_path.iterdir()
105
+ if f.is_file() and re.match(r"step-\d+", f.name) and f.suffix == ".md"
106
+ ])
107
+
108
+
109
+ def parse_steps_completed(value: str) -> list[int]:
110
+ """Parse steps completed array from string like '[1, 2, 3]'."""
111
+ if not value or value == "[]":
112
+ return []
113
+ # Extract numbers from the bracket notation
114
+ return [int(n) for n in re.findall(r"\d+", value)]
115
+
116
+
117
+ def format_steps_completed(steps: list[int]) -> str:
118
+ """Format steps list as bracket notation."""
119
+ if not steps:
120
+ return "[]"
121
+ return "[" + ", ".join(str(s) for s in steps) + "]"
122
+
123
+
124
+ def find_next_step_file(steps_path: Path, step_number: int) -> Path | None:
125
+ """Find step file for a given step number."""
126
+ padded = f"{step_number:02d}"
127
+ matches = sorted([
128
+ f for f in steps_path.iterdir()
129
+ if f.is_file()
130
+ and (f.name.startswith(f"step-{padded}") or f.name.startswith(f"step-{step_number}-"))
131
+ and f.suffix == ".md"
132
+ ])
133
+ return matches[0] if matches else None
134
+
135
+
136
+ def strip_frontmatter(content: str) -> str:
137
+ """Remove YAML frontmatter from step file content."""
138
+ if not content.startswith("---"):
139
+ return content
140
+ # Find the closing ---
141
+ end = content.find("---", 3)
142
+ if end == -1:
143
+ return content
144
+ return content[end + 3:].lstrip("\n")
145
+
146
+
147
+ def main() -> int:
148
+ parser = argparse.ArgumentParser(
149
+ description="Complete the current step of a stepped workflow"
150
+ )
151
+ parser.add_argument("name", nargs="?", default=None,
152
+ help="Workflow name (auto-detects from session if omitted)")
153
+ parser.add_argument("--step", type=int, default=None, dest="step_override",
154
+ help="Complete a specific step number instead of current step")
155
+ args = parser.parse_args()
156
+
157
+ project_root = find_project_root()
158
+ workflows_dir = project_root / ".pennyfarthing" / "workflows"
159
+ session_dir = project_root / ".session"
160
+
161
+ # Find session file
162
+ session_file, workflow_name = find_session_file(session_dir, args.name)
163
+ content = session_file.read_text()
164
+
165
+ # Parse session state
166
+ current_step_str = parse_session_field(content, "Current Step") or "1"
167
+ current_step = int(current_step_str)
168
+ mode = parse_session_field(content, "Mode") or "create"
169
+ status = parse_session_field(content, "Status") or "in_progress"
170
+ steps_completed_str = parse_session_field(content, "Steps Completed") or "[]"
171
+
172
+ # Check if already completed
173
+ if status == "completed":
174
+ print(f"# Workflow Already Completed: {workflow_name}")
175
+ print()
176
+ print("This workflow has already been completed.")
177
+ print()
178
+ print("To start a new session, delete the session file:")
179
+ print("```bash")
180
+ print(f'rm "{session_file}"')
181
+ print("```")
182
+ print()
183
+ print(f"Then run `/workflow start {workflow_name}`")
184
+ return 0
185
+
186
+ # Determine which step to complete
187
+ completing_step = args.step_override if args.step_override is not None else current_step
188
+
189
+ # Find workflow file and resolve steps path
190
+ workflow_file = find_workflow_file(workflows_dir, workflow_name)
191
+ workflow_dir = workflow_file.parent
192
+
193
+ with open(workflow_file) as f:
194
+ wf_data = yaml.safe_load(f)
195
+
196
+ wf = wf_data.get("workflow", {})
197
+
198
+ # Resolve steps path based on mode
199
+ modes = wf.get("modes", {})
200
+ mode_path = modes.get(mode)
201
+ if mode_path and mode_path != "null":
202
+ steps_path_str = mode_path
203
+ else:
204
+ steps_path_str = wf.get("steps", {}).get("path", ".")
205
+
206
+ # Resolve relative path
207
+ if steps_path_str.startswith("./"):
208
+ steps_path = workflow_dir / steps_path_str[2:]
209
+ elif not Path(steps_path_str).is_absolute():
210
+ steps_path = project_root / steps_path_str
211
+ else:
212
+ steps_path = Path(steps_path_str)
213
+
214
+ # Count total steps
215
+ step_count = count_steps(steps_path)
216
+
217
+ # Update Steps Completed array
218
+ steps_completed = parse_steps_completed(steps_completed_str)
219
+ if completing_step not in steps_completed:
220
+ steps_completed.append(completing_step)
221
+ new_steps_completed = format_steps_completed(steps_completed)
222
+
223
+ # Calculate new current step
224
+ next_step = completing_step + 1
225
+
226
+ # Count completed and calculate percentage
227
+ completed_count = len(steps_completed)
228
+ completion_pct = (completed_count * 100 // step_count) if step_count > 0 else 0
229
+
230
+ # Determine new status
231
+ new_status = "completed" if completed_count >= step_count else "in_progress"
232
+
233
+ # Update timestamp
234
+ now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
235
+
236
+ # Update session file content
237
+ content = re.sub(
238
+ r"^- \*\*Current Step:\*\*.*$",
239
+ f"- **Current Step:** {next_step}",
240
+ content, flags=re.MULTILINE
241
+ )
242
+ content = re.sub(
243
+ r"^- \*\*Steps Completed:\*\*.*$",
244
+ f"- **Steps Completed:** {new_steps_completed}",
245
+ content, flags=re.MULTILINE
246
+ )
247
+ content = re.sub(
248
+ r"^- \*\*Last Updated:\*\*.*$",
249
+ f"- **Last Updated:** {now}",
250
+ content, flags=re.MULTILINE
251
+ )
252
+ content = re.sub(
253
+ r"^- \*\*Status:\*\*.*$",
254
+ f"- **Status:** {new_status}",
255
+ content, flags=re.MULTILINE
256
+ )
257
+ content = re.sub(
258
+ r"^- Completion:.*$",
259
+ f"- Completion: {completion_pct}%",
260
+ content, flags=re.MULTILINE
261
+ )
262
+
263
+ # Write updated session file
264
+ session_file.write_text(content)
265
+
266
+ # Output result
267
+ if new_status == "completed":
268
+ print(f"# Workflow Complete: {workflow_name}")
269
+ print()
270
+ print(f"All {step_count} steps completed!")
271
+ print()
272
+ print(f"**Final Progress:** {completion_pct}%")
273
+ print(f"**Steps Completed:** {new_steps_completed}")
274
+ print()
275
+ print(f"Session updated: {session_file}")
276
+ else:
277
+ print(f"# Step {completing_step} Complete")
278
+ print()
279
+ print(f"**Progress:** Step {next_step} of {step_count} ({completion_pct}% complete)")
280
+ print(f"**Steps Completed:** {new_steps_completed}")
281
+ print()
282
+ print("---")
283
+ print()
284
+ print(f"## Step {next_step} of {step_count}")
285
+ print()
286
+
287
+ # Find and output next step file
288
+ next_step_file = find_next_step_file(steps_path, next_step)
289
+ if next_step_file:
290
+ step_content = next_step_file.read_text()
291
+ print(strip_frontmatter(step_content))
292
+
293
+ print()
294
+ print("---")
295
+ print()
296
+ print("**Controls:**")
297
+ print("- `C` - Continue to next step")
298
+ print("- `/workflow status` - Check progress")
299
+
300
+ return 0
301
+
302
+
303
+ if __name__ == "__main__":
304
+ sys.exit(main())
@@ -0,0 +1,154 @@
1
+ #!/bin/bash
2
+ # Finish a story: archive, merge PR, transition Jira, update sprint YAML
3
+ # Usage: finish-story.sh <story-id> [--dry-run]
4
+ #
5
+ # Example: finish-story.sh MSSCI-12052
6
+ # finish-story.sh MSSCI-12052 --dry-run
7
+ #
8
+ # Prerequisites:
9
+ # - Session file exists at .session/{story-id}-session.md
10
+ # - PR is approved and mergeable
11
+ # - Reviewer has approved (phase: finish in session)
12
+ #
13
+ # This script performs:
14
+ # 1. Archive session file to sprint/archive/{jira-key}-session.md
15
+ # 2. Squash merge PR and delete remote branch
16
+ # 3. Transition Jira to Done
17
+ # 4. Update sprint YAML (status: done, completed date)
18
+ # 5. Clean up local branch and session file
19
+
20
+ set -euo pipefail
21
+
22
+ STORY_ID="${1:-}"
23
+ DRY_RUN=false
24
+
25
+ # Parse options
26
+ for arg in "$@"; do
27
+ case $arg in
28
+ --dry-run)
29
+ DRY_RUN=true
30
+ shift
31
+ ;;
32
+ esac
33
+ done
34
+
35
+ if [[ -z "$STORY_ID" ]]; then
36
+ echo "Usage: finish-story.sh <story-id> [--dry-run]"
37
+ echo ""
38
+ echo "Options:"
39
+ echo " --dry-run Show what would be done without executing"
40
+ exit 1
41
+ fi
42
+
43
+ # Find project root
44
+ source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
45
+
46
+ SESSION_FILE="$PROJECT_ROOT/.session/${STORY_ID}-session.md"
47
+ SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
48
+ ARCHIVE_DIR="$PROJECT_ROOT/sprint/archive"
49
+
50
+ # Ensure archive directory exists
51
+ mkdir -p "$ARCHIVE_DIR"
52
+
53
+ # Validate session file exists
54
+ if [[ ! -f "$SESSION_FILE" ]]; then
55
+ echo "Error: Session file not found: $SESSION_FILE"
56
+ exit 1
57
+ fi
58
+
59
+ # Extract metadata from session file (handle both "**Jira:**" and "- **Jira:**" formats)
60
+ # Also handle markdown link format: [MSSCI-12721](https://...)
61
+ JIRA_KEY=$(grep -E '\*\*Jira:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Jira:\*\* //' | sed 's/\[//' | sed 's/\].*//' | tr -d ' ' || echo "")
62
+ # Extract branch - strip any trailing annotations like "(pushed)"
63
+ BRANCH=$(grep -E '\*\*Branch:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Branch:\*\* //' | sed 's/ *(.*//' | tr -d ' ' || echo "")
64
+
65
+ # Try to get PR number from session file first (format: **PR:** #422 - title)
66
+ PR_NUMBER=$(grep -E '\*\*PR:\*\*' "$SESSION_FILE" | sed 's/.*#\([0-9]*\).*/\1/' || echo "")
67
+
68
+ # Fallback: try to get Jira key from sprint YAML if not in session
69
+ if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
70
+ JIRA_KEY=$(yq ".epics[].stories[] | select(.id == \"$STORY_ID\") | .jira // \"\"" "$SPRINT_FILE" 2>/dev/null | head -1 || echo "")
71
+ fi
72
+
73
+ if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
74
+ echo "Error: Could not determine Jira key for story $STORY_ID"
75
+ echo "Check session file or sprint YAML for jira: field"
76
+ exit 1
77
+ fi
78
+
79
+ # Fallback: get PR number from GitHub if not in session file
80
+ if [[ -z "$PR_NUMBER" ]] && [[ -n "$BRANCH" ]]; then
81
+ PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || echo "")
82
+ fi
83
+
84
+ TODAY=$(date +%Y-%m-%d)
85
+
86
+ echo "=== Finish Story: $STORY_ID ==="
87
+ echo "Jira Key: $JIRA_KEY"
88
+ echo "Branch: ${BRANCH:-none}"
89
+ echo "PR: ${PR_NUMBER:-none}"
90
+ echo ""
91
+
92
+ if $DRY_RUN; then
93
+ echo "[DRY RUN] Would perform:"
94
+ echo " 1. Archive session → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
95
+ if [[ -n "$PR_NUMBER" ]]; then
96
+ echo " 2. Merge PR #$PR_NUMBER (squash, delete branch)"
97
+ else
98
+ echo " 2. No PR to merge"
99
+ fi
100
+ echo " 3. Transition $JIRA_KEY to Done"
101
+ echo " 4. Update sprint YAML (status: done, completed: $TODAY)"
102
+ echo " 5. Delete local branch: $BRANCH"
103
+ echo " 6. Remove session file"
104
+ exit 0
105
+ fi
106
+
107
+ # Step 1: Archive session file
108
+ echo "1. Archiving session file..."
109
+ cp "$SESSION_FILE" "$ARCHIVE_DIR/${JIRA_KEY}-session.md"
110
+ echo " → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
111
+
112
+ # Step 2: Merge PR (if exists)
113
+ if [[ -n "$PR_NUMBER" ]]; then
114
+ echo "2. Merging PR #$PR_NUMBER..."
115
+ gh pr merge "$PR_NUMBER" --squash --delete-branch || {
116
+ echo " Warning: PR merge failed (may already be merged)"
117
+ }
118
+ else
119
+ echo "2. No PR found for branch $BRANCH (skipping merge)"
120
+ fi
121
+
122
+ # Step 3: Transition Jira to Done
123
+ echo "3. Transitioning Jira to Done..."
124
+ jira issue move "$JIRA_KEY" "Done" 2>/dev/null || {
125
+ echo " Warning: Jira transition failed (may already be Done)"
126
+ }
127
+
128
+ # Step 4: Update sprint YAML
129
+ echo "4. Updating sprint YAML..."
130
+ # Update status to done
131
+ yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).status = \"done\"" "$SPRINT_FILE"
132
+ # Add completed date
133
+ yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).completed = \"$TODAY\"" "$SPRINT_FILE"
134
+ # Remove assigned_to (no longer in progress)
135
+ yq eval -i "del((.epics[].stories[] | select(.id == \"$STORY_ID\")).assigned_to)" "$SPRINT_FILE"
136
+ echo " → status: done, completed: $TODAY"
137
+
138
+ # Step 5: Clean up git
139
+ echo "5. Cleaning up git..."
140
+ git checkout develop 2>/dev/null || git checkout main 2>/dev/null || true
141
+ git pull origin "$(git branch --show-current)" 2>/dev/null || true
142
+
143
+ if [[ -n "$BRANCH" ]]; then
144
+ git branch -d "$BRANCH" 2>/dev/null || echo " Local branch already deleted"
145
+ fi
146
+
147
+ # Step 6: Remove session file
148
+ echo "6. Removing session file..."
149
+ rm "$SESSION_FILE"
150
+
151
+ echo ""
152
+ echo "=== Story $STORY_ID Complete ==="
153
+ echo "Archived: sprint/archive/${JIRA_KEY}-session.md"
154
+ echo "Jira: https://1898andco.atlassian.net/browse/$JIRA_KEY"
@@ -0,0 +1,222 @@
1
+ #!/bin/bash
2
+ # Fix session file phase tracking when handoffs didn't update properly
3
+ # Usage: fix-session-phase.sh <story-id> <target-phase> [--dry-run]
4
+ #
5
+ # Example: fix-session-phase.sh 56-1 review
6
+ # fix-session-phase.sh MSSCI-12190 approved --dry-run
7
+ #
8
+ # This script detects the current phase, validates the target phase is reachable,
9
+ # and updates the session file's Workflow Tracking section:
10
+ # - Updates **Phase:** field to target phase
11
+ # - Adds missing rows to Phase History table
12
+ # - Adds missing rows to Handoff History table
13
+ #
14
+ # Valid phases for TDD workflow: setup → red → green → review → approved → finish
15
+ # Valid phases for trivial workflow: setup → implement → review → approved → finish
16
+
17
+ set -euo pipefail
18
+
19
+ STORY_ID="${1:-}"
20
+ TARGET_PHASE="${2:-}"
21
+ DRY_RUN=false
22
+
23
+ # Parse options
24
+ for arg in "$@"; do
25
+ case $arg in
26
+ --dry-run)
27
+ DRY_RUN=true
28
+ ;;
29
+ esac
30
+ done
31
+
32
+ if [[ -z "$STORY_ID" ]] || [[ -z "$TARGET_PHASE" ]]; then
33
+ echo "Usage: fix-session-phase.sh <story-id> <target-phase> [--dry-run]"
34
+ echo ""
35
+ echo "Arguments:"
36
+ echo " story-id Story ID (e.g., 56-1 or MSSCI-12190)"
37
+ echo " target-phase Target phase to set (e.g., review, approved, finish)"
38
+ echo ""
39
+ echo "Options:"
40
+ echo " --dry-run Show what would be done without executing"
41
+ echo ""
42
+ echo "Examples:"
43
+ echo " fix-session-phase.sh 56-1 review # Update to review phase"
44
+ echo " fix-session-phase.sh 56-1 approved # Update to approved phase"
45
+ echo " fix-session-phase.sh 56-1 finish --dry-run # Preview finish update"
46
+ exit 1
47
+ fi
48
+
49
+ # Find project root
50
+ source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
51
+
52
+ # Try multiple session file naming patterns
53
+ SESSION_FILE=""
54
+ STORY_ID_LOWER=$(echo "$STORY_ID" | tr '[:upper:]' '[:lower:]')
55
+ for pattern in "${STORY_ID}-session.md" "${STORY_ID_LOWER}-session.md"; do
56
+ if [[ -f "$PROJECT_ROOT/.session/$pattern" ]]; then
57
+ SESSION_FILE="$PROJECT_ROOT/.session/$pattern"
58
+ break
59
+ fi
60
+ done
61
+
62
+ # Also try without the epic prefix (e.g., MSSCI-12190 might be in 56-1-session.md)
63
+ if [[ -z "$SESSION_FILE" ]]; then
64
+ # Search for session files containing this story ID
65
+ found=$(grep -l "Jira:.*$STORY_ID\|ID:.*$STORY_ID" "$PROJECT_ROOT/.session/"*-session.md 2>/dev/null | head -1 || echo "")
66
+ if [[ -n "$found" ]]; then
67
+ SESSION_FILE="$found"
68
+ fi
69
+ fi
70
+
71
+ if [[ -z "$SESSION_FILE" ]] || [[ ! -f "$SESSION_FILE" ]]; then
72
+ echo "Error: Session file not found for story $STORY_ID"
73
+ echo "Searched in: $PROJECT_ROOT/.session/"
74
+ exit 1
75
+ fi
76
+
77
+ echo "Session file: $SESSION_FILE"
78
+
79
+ # Extract current state
80
+ CURRENT_PHASE=$(grep -E '^\*\*Phase:\*\*' "$SESSION_FILE" | sed 's/\*\*Phase:\*\* //' | tr -d ' ' || echo "unknown")
81
+ WORKFLOW=$(grep -E '^\*\*Workflow:\*\*' "$SESSION_FILE" | head -1 | sed 's/\*\*Workflow:\*\* //' | tr -d ' ' || echo "tdd")
82
+ PHASE_STARTED=$(grep -E '^\*\*Phase Started:\*\*' "$SESSION_FILE" | sed 's/\*\*Phase Started:\*\* //' | tr -d ' ' || echo "")
83
+
84
+ echo "Current phase: $CURRENT_PHASE"
85
+ echo "Target phase: $TARGET_PHASE"
86
+ echo "Workflow: $WORKFLOW"
87
+
88
+ # Define valid phase sequences
89
+ case "$WORKFLOW" in
90
+ tdd)
91
+ PHASES=("setup" "red" "green" "review" "approved" "finish")
92
+ AGENTS=("sm" "tea" "dev" "reviewer" "sm" "sm")
93
+ GATES=("manual" "tests_fail" "tests_pass" "approval" "complete" "")
94
+ ;;
95
+ trivial)
96
+ PHASES=("setup" "implement" "review" "approved" "finish")
97
+ AGENTS=("sm" "dev" "reviewer" "sm" "sm")
98
+ GATES=("manual" "tests_pass" "approval" "complete" "")
99
+ ;;
100
+ *)
101
+ echo "Warning: Unknown workflow '$WORKFLOW', assuming TDD"
102
+ PHASES=("setup" "red" "green" "review" "approved" "finish")
103
+ AGENTS=("sm" "tea" "dev" "reviewer" "sm" "sm")
104
+ GATES=("manual" "tests_fail" "tests_pass" "approval" "complete" "")
105
+ ;;
106
+ esac
107
+
108
+ # Find indices
109
+ CURRENT_IDX=-1
110
+ TARGET_IDX=-1
111
+ for i in "${!PHASES[@]}"; do
112
+ if [[ "${PHASES[$i]}" == "$CURRENT_PHASE" ]]; then
113
+ CURRENT_IDX=$i
114
+ fi
115
+ if [[ "${PHASES[$i]}" == "$TARGET_PHASE" ]]; then
116
+ TARGET_IDX=$i
117
+ fi
118
+ done
119
+
120
+ if [[ $CURRENT_IDX -eq -1 ]]; then
121
+ echo "Error: Current phase '$CURRENT_PHASE' not found in $WORKFLOW workflow"
122
+ echo "Valid phases: ${PHASES[*]}"
123
+ exit 1
124
+ fi
125
+
126
+ if [[ $TARGET_IDX -eq -1 ]]; then
127
+ echo "Error: Target phase '$TARGET_PHASE' not found in $WORKFLOW workflow"
128
+ echo "Valid phases: ${PHASES[*]}"
129
+ exit 1
130
+ fi
131
+
132
+ if [[ $TARGET_IDX -le $CURRENT_IDX ]]; then
133
+ echo "Error: Target phase '$TARGET_PHASE' is not ahead of current phase '$CURRENT_PHASE'"
134
+ echo "Phase sequence: ${PHASES[*]}"
135
+ exit 1
136
+ fi
137
+
138
+ # Calculate what transitions are needed
139
+ echo ""
140
+ echo "Transitions needed:"
141
+ NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
142
+ TRANSITIONS=()
143
+
144
+ for ((i=CURRENT_IDX; i<TARGET_IDX; i++)); do
145
+ FROM_PHASE="${PHASES[$i]}"
146
+ TO_PHASE="${PHASES[$((i+1))]}"
147
+ FROM_AGENT="${AGENTS[$i]}"
148
+ TO_AGENT="${AGENTS[$((i+1))]}"
149
+ GATE="${GATES[$((i+1))]}"
150
+
151
+ echo " $FROM_PHASE ($FROM_AGENT) → $TO_PHASE ($TO_AGENT) [gate: $GATE]"
152
+ TRANSITIONS+=("$FROM_PHASE|$TO_PHASE|$FROM_AGENT|$TO_AGENT|$GATE")
153
+ done
154
+
155
+ if [[ "$DRY_RUN" == "true" ]]; then
156
+ echo ""
157
+ echo "[DRY RUN] Would update session file with:"
158
+ echo " - **Phase:** $TARGET_PHASE"
159
+ echo " - **Phase Started:** $NOW"
160
+ echo " - Phase History: close out $CURRENT_PHASE, add intermediate phases"
161
+ echo " - Handoff History: add ${#TRANSITIONS[@]} handoff(s)"
162
+ exit 0
163
+ fi
164
+
165
+ echo ""
166
+ echo "Updating session file..."
167
+
168
+ # Build the Phase History additions
169
+ PHASE_HISTORY_ADDITIONS=""
170
+ HANDOFF_HISTORY_ADDITIONS=""
171
+ PREV_END="$NOW"
172
+
173
+ for transition in "${TRANSITIONS[@]}"; do
174
+ IFS='|' read -r FROM_PHASE TO_PHASE FROM_AGENT TO_AGENT GATE <<< "$transition"
175
+
176
+ # Add phase history row (close out the FROM phase)
177
+ # We'll use NOW for ended time since we don't know actual times
178
+ PHASE_HISTORY_ADDITIONS+="| $FROM_PHASE | - | $NOW | - |\n"
179
+
180
+ # Add handoff history row
181
+ HANDOFF_HISTORY_ADDITIONS+="| $FROM_AGENT | $TO_AGENT | $GATE | PASSED | $NOW |\n"
182
+ done
183
+
184
+ # Update the **Phase:** line
185
+ sed -i.bak "s/^\*\*Phase:\*\*.*/\*\*Phase:\*\* $TARGET_PHASE/" "$SESSION_FILE"
186
+
187
+ # Update the **Phase Started:** line
188
+ sed -i.bak "s/^\*\*Phase Started:\*\*.*/\*\*Phase Started:\*\* $NOW/" "$SESSION_FILE"
189
+
190
+ # Close out the current phase in Phase History (update the row that has "| - | - |" at the end)
191
+ # This is tricky - we need to find the row for current phase and add end time
192
+ # For now, we'll add a note about manual review needed
193
+
194
+ # Add handoff history rows before the "## Story Context" section
195
+ if [[ -n "$HANDOFF_HISTORY_ADDITIONS" ]]; then
196
+ # Find the last handoff history row and add after it
197
+ # The handoff history table ends before a blank line or next section
198
+
199
+ # Use awk to insert after the last handoff history row
200
+ awk -v additions="$HANDOFF_HISTORY_ADDITIONS" '
201
+ /^\| .* \| .* \| .* \| .* \| .*\|$/ && /PASSED|FAILED/ {
202
+ last_handoff = NR
203
+ last_handoff_line = $0
204
+ }
205
+ {
206
+ print
207
+ if (NR == last_handoff && additions != "") {
208
+ printf "%s", additions
209
+ }
210
+ }
211
+ ' "$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
212
+ fi
213
+
214
+ # Clean up backup
215
+ rm -f "$SESSION_FILE.bak"
216
+
217
+ echo ""
218
+ echo "✓ Session file updated"
219
+ echo " Phase: $CURRENT_PHASE → $TARGET_PHASE"
220
+ echo " Handoffs added: ${#TRANSITIONS[@]}"
221
+ echo ""
222
+ echo "Note: Phase History end times set to now. Review and adjust if needed."