@pennyfarthing/core 10.0.3 → 10.1.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 (282) hide show
  1. package/README.md +9 -7
  2. package/package.json +7 -1
  3. package/packages/core/dist/cli/commands/cyclist.d.ts +5 -1
  4. package/packages/core/dist/cli/commands/cyclist.d.ts.map +1 -1
  5. package/packages/core/dist/cli/commands/cyclist.js +4 -4
  6. package/packages/core/dist/cli/commands/cyclist.js.map +1 -1
  7. package/packages/core/dist/cli/commands/cyclist.test.js +2 -2
  8. package/packages/core/dist/cli/commands/cyclist.test.js.map +1 -1
  9. package/packages/core/dist/cli/commands/doctor-legacy.test.js +17 -16
  10. package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
  11. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  12. package/packages/core/dist/cli/commands/doctor.js +251 -4
  13. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  14. package/packages/core/dist/cli/commands/init.d.ts +7 -0
  15. package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
  16. package/packages/core/dist/cli/commands/init.js +43 -7
  17. package/packages/core/dist/cli/commands/init.js.map +1 -1
  18. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  19. package/packages/core/dist/cli/commands/update.js +26 -0
  20. package/packages/core/dist/cli/commands/update.js.map +1 -1
  21. package/packages/core/dist/cli/index.js +1 -1
  22. package/packages/core/dist/cli/index.js.map +1 -1
  23. package/packages/core/dist/cli/ocean-profiles.test.js +1 -1
  24. package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
  25. package/packages/core/dist/cli/utils/files.d.ts +10 -0
  26. package/packages/core/dist/cli/utils/files.d.ts.map +1 -1
  27. package/packages/core/dist/cli/utils/files.js +35 -0
  28. package/packages/core/dist/cli/utils/files.js.map +1 -1
  29. package/packages/core/dist/cli/utils/python.d.ts +22 -0
  30. package/packages/core/dist/cli/utils/python.d.ts.map +1 -0
  31. package/packages/core/dist/cli/utils/python.js +102 -0
  32. package/packages/core/dist/cli/utils/python.js.map +1 -0
  33. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  34. package/packages/core/dist/cli/utils/settings.js +10 -0
  35. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  36. package/packages/core/dist/scripts/generate-report.d.ts.map +1 -1
  37. package/packages/core/dist/scripts/generate-report.js +11 -7
  38. package/packages/core/dist/scripts/generate-report.js.map +1 -1
  39. package/packages/core/dist/scripts/generate-spider-report.d.ts.map +1 -1
  40. package/packages/core/dist/scripts/generate-spider-report.js +12 -8
  41. package/packages/core/dist/scripts/generate-spider-report.js.map +1 -1
  42. package/packages/core/dist/scripts/generate-spider.d.ts.map +1 -1
  43. package/packages/core/dist/scripts/generate-spider.js +6 -4
  44. package/packages/core/dist/scripts/generate-spider.js.map +1 -1
  45. package/packages/core/dist/scripts/generate-spider.test.js +2 -2
  46. package/packages/core/dist/scripts/generate-spider.test.js.map +1 -1
  47. package/pennyfarthing-dist/agents/README.md +1 -3
  48. package/pennyfarthing-dist/agents/architect.md +0 -6
  49. package/pennyfarthing-dist/agents/devops.md +0 -6
  50. package/pennyfarthing-dist/agents/orchestrator.md +0 -6
  51. package/pennyfarthing-dist/agents/pm.md +1 -7
  52. package/pennyfarthing-dist/agents/sm-finish.md +1 -1
  53. package/pennyfarthing-dist/agents/sm-setup.md +2 -2
  54. package/pennyfarthing-dist/agents/sm.md +4 -11
  55. package/pennyfarthing-dist/commands/architect.md +11 -3
  56. package/pennyfarthing-dist/commands/close-epic.md +24 -131
  57. package/pennyfarthing-dist/commands/create-theme.md +14 -24
  58. package/pennyfarthing-dist/commands/dev.md +11 -3
  59. package/pennyfarthing-dist/commands/devops.md +11 -3
  60. package/pennyfarthing-dist/commands/health-check.md +1 -3
  61. package/pennyfarthing-dist/commands/help.md +8 -12
  62. package/pennyfarthing-dist/commands/list-themes.md +14 -16
  63. package/pennyfarthing-dist/commands/orchestrator.md +11 -3
  64. package/pennyfarthing-dist/commands/parallel-work.md +1 -3
  65. package/pennyfarthing-dist/commands/pm.md +11 -3
  66. package/pennyfarthing-dist/commands/prime.md +6 -6
  67. package/pennyfarthing-dist/commands/repo-status.md +2 -2
  68. package/pennyfarthing-dist/commands/reviewer.md +11 -3
  69. package/pennyfarthing-dist/commands/run-ci.md +1 -1
  70. package/pennyfarthing-dist/commands/set-theme.md +14 -51
  71. package/pennyfarthing-dist/commands/setup.md +1 -1
  72. package/pennyfarthing-dist/commands/show-theme.md +14 -16
  73. package/pennyfarthing-dist/commands/sm.md +11 -3
  74. package/pennyfarthing-dist/commands/sprint.md +8 -8
  75. package/pennyfarthing-dist/commands/tea.md +11 -3
  76. package/pennyfarthing-dist/commands/tech-writer.md +11 -3
  77. package/pennyfarthing-dist/commands/theme-maker.md +14 -671
  78. package/pennyfarthing-dist/commands/theme.md +95 -0
  79. package/pennyfarthing-dist/commands/ux-designer.md +11 -3
  80. package/pennyfarthing-dist/commands/work.md +3 -5
  81. package/pennyfarthing-dist/guides/agent-coordination.md +11 -13
  82. package/pennyfarthing-dist/guides/agent-template-tactical.md +2 -3
  83. package/pennyfarthing-dist/guides/command-tag-taxonomy.md +212 -0
  84. package/pennyfarthing-dist/guides/hooks.md +5 -5
  85. package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +3 -3
  86. package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +9 -59
  87. package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +4 -5
  88. package/pennyfarthing-dist/guides/prime.md +2 -2
  89. package/pennyfarthing-dist/guides/skill-schema.md +25 -26
  90. package/pennyfarthing-dist/guides/xml-tags.md +2 -2
  91. package/pennyfarthing-dist/scripts/README.md +2 -2
  92. package/pennyfarthing-dist/scripts/core/agent-session.sh +6 -2
  93. package/pennyfarthing-dist/scripts/core/prime.sh +8 -10
  94. package/pennyfarthing-dist/scripts/git/git-status-all.sh +1 -1
  95. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +8 -6
  96. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +3 -3
  97. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +14 -12
  98. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +4 -3
  99. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +11 -5
  100. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +1 -1
  101. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  102. package/pennyfarthing-dist/scripts/misc/repo-utils.sh +3 -3
  103. package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +1 -2
  104. package/pennyfarthing-dist/scripts/sprint/README.md +32 -17
  105. package/pennyfarthing-dist/scripts/story/README.md +1 -1
  106. package/pennyfarthing-dist/scripts/test/test-setup.sh +1 -1
  107. package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +5 -5
  108. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +3 -79
  109. package/pennyfarthing-dist/scripts/theme/README.md +1 -1
  110. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +0 -1
  111. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +62 -17
  112. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +2 -2
  113. package/pennyfarthing-dist/skills/skill-registry.yaml +41 -28
  114. package/pennyfarthing-dist/skills/sprint/skill.md +386 -68
  115. package/pennyfarthing-dist/skills/story/skill.md +14 -206
  116. package/pennyfarthing-dist/skills/theme/skill.md +290 -75
  117. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +23 -166
  118. package/pennyfarthing-dist/skills/workflow/skill.md +4 -4
  119. package/pennyfarthing-dist/templates/agent-scopes.yaml.template +0 -11
  120. package/pennyfarthing-dist/templates/auto-load-sm.sh.template +14 -0
  121. package/pennyfarthing-dist/templates/settings.local.json.template +9 -0
  122. package/pennyfarthing-dist/workflows/2party-tdd.yaml +399 -0
  123. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +42 -25
  124. package/pennyfarthing-dist/workflows/git-cleanup.yaml +1 -1
  125. package/pennyfarthing-dist/workflows/project-setup/steps/step-10-complete.md +1 -1
  126. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  127. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  128. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  129. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  130. package/pennyfarthing_scripts/cli.py +15 -0
  131. package/pennyfarthing_scripts/codemarkers/__init__.py +19 -0
  132. package/pennyfarthing_scripts/codemarkers/__main__.py +6 -0
  133. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  134. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  135. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  136. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  137. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  138. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  139. package/pennyfarthing_scripts/codemarkers/analyze.py +326 -0
  140. package/pennyfarthing_scripts/codemarkers/cli.py +129 -0
  141. package/pennyfarthing_scripts/codemarkers/formatters.py +89 -0
  142. package/pennyfarthing_scripts/codemarkers/models.py +45 -0
  143. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  144. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  145. package/pennyfarthing_scripts/common/config.py +2 -1
  146. package/pennyfarthing_scripts/complexity/__init__.py +15 -0
  147. package/pennyfarthing_scripts/complexity/__main__.py +6 -0
  148. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  149. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  150. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  151. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  152. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  153. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  154. package/pennyfarthing_scripts/complexity/analyze.py +207 -0
  155. package/pennyfarthing_scripts/complexity/cli.py +78 -0
  156. package/pennyfarthing_scripts/complexity/formatters.py +64 -0
  157. package/pennyfarthing_scripts/complexity/models.py +32 -0
  158. package/pennyfarthing_scripts/deadcode/__init__.py +6 -0
  159. package/pennyfarthing_scripts/deadcode/__main__.py +6 -0
  160. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  161. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  162. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  163. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  164. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  165. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  166. package/pennyfarthing_scripts/deadcode/analyze.py +323 -0
  167. package/pennyfarthing_scripts/deadcode/cli.py +163 -0
  168. package/pennyfarthing_scripts/deadcode/formatters.py +106 -0
  169. package/pennyfarthing_scripts/deadcode/models.py +54 -0
  170. package/pennyfarthing_scripts/dependencies/__init__.py +20 -0
  171. package/pennyfarthing_scripts/dependencies/__main__.py +5 -0
  172. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  173. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  174. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  175. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  176. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  177. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  178. package/pennyfarthing_scripts/dependencies/analyze.py +155 -0
  179. package/pennyfarthing_scripts/dependencies/cli.py +72 -0
  180. package/pennyfarthing_scripts/dependencies/formatters.py +63 -0
  181. package/pennyfarthing_scripts/dependencies/models.py +39 -0
  182. package/pennyfarthing_scripts/healthscore/__init__.py +21 -0
  183. package/pennyfarthing_scripts/healthscore/__main__.py +6 -0
  184. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  185. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  186. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  187. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  188. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  189. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  190. package/pennyfarthing_scripts/healthscore/analyze.py +161 -0
  191. package/pennyfarthing_scripts/healthscore/cli.py +76 -0
  192. package/pennyfarthing_scripts/healthscore/formatters.py +46 -0
  193. package/pennyfarthing_scripts/healthscore/models.py +44 -0
  194. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/hotspots/analyze.py +28 -1
  201. package/pennyfarthing_scripts/hotspots/cli.py +11 -9
  202. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  205. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/jira/bidirectional.py +42 -15
  210. package/pennyfarthing_scripts/jira/cli.py +78 -1
  211. package/pennyfarthing_scripts/jira/client.py +28 -0
  212. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  213. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  214. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  215. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  216. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  217. package/pennyfarthing_scripts/prime/workflow.py +5 -3
  218. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  219. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  220. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  221. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  222. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  223. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  225. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  229. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  230. package/pennyfarthing_scripts/sprint/archive.py +63 -6
  231. package/pennyfarthing_scripts/sprint/archive_epic.py +198 -85
  232. package/pennyfarthing_scripts/sprint/cli.py +1565 -65
  233. package/pennyfarthing_scripts/sprint/epic_add.py +173 -0
  234. package/pennyfarthing_scripts/sprint/loader.py +46 -2
  235. package/pennyfarthing_scripts/sprint/story_add.py +202 -27
  236. package/pennyfarthing_scripts/sprint/story_finish.py +211 -0
  237. package/pennyfarthing_scripts/sprint/validate_cmd.py +44 -5
  238. package/pennyfarthing_scripts/sprint/validator.py +13 -3
  239. package/pennyfarthing_scripts/sprint/work.py +43 -3
  240. package/pennyfarthing_scripts/sprint/yaml_io.py +124 -15
  241. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  242. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  243. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  244. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  245. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  246. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  247. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  248. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  249. package/pennyfarthing_scripts/tests/test_codemarkers.py +682 -0
  250. package/pennyfarthing_scripts/tests/test_healthscore.py +524 -0
  251. package/pennyfarthing_scripts/tests/test_sprint_package.py +166 -0
  252. package/pennyfarthing_scripts/tests/test_yaml_io.py +117 -0
  253. package/pennyfarthing_scripts/theme/__init__.py +5 -0
  254. package/pennyfarthing_scripts/theme/__main__.py +6 -0
  255. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  256. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  257. package/pennyfarthing_scripts/theme/cli.py +286 -0
  258. package/scripts/README.md +53 -0
  259. package/scripts/postinstall.cjs +34 -0
  260. package/pennyfarthing-dist/agents/workflow-status-check.md +0 -96
  261. package/pennyfarthing-dist/scripts/sprint/archive-story.sh +0 -133
  262. package/pennyfarthing-dist/scripts/sprint/available-stories.sh +0 -91
  263. package/pennyfarthing-dist/scripts/sprint/check-story.sh +0 -158
  264. package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +0 -52
  265. package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +0 -63
  266. package/pennyfarthing-dist/scripts/sprint/list-future.sh +0 -145
  267. package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +0 -110
  268. package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +0 -148
  269. package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +0 -415
  270. package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +0 -33
  271. package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +0 -230
  272. package/pennyfarthing-dist/scripts/sprint/sprint-status.sh +0 -134
  273. package/pennyfarthing-dist/scripts/sprint/validate-sprint-yaml.sh +0 -139
  274. package/pennyfarthing-dist/skills/sprint/scripts/archive-story.sh +0 -101
  275. package/pennyfarthing-dist/skills/sprint/scripts/available-stories.sh +0 -97
  276. package/pennyfarthing-dist/skills/sprint/scripts/check-story.sh +0 -164
  277. package/pennyfarthing-dist/skills/sprint/scripts/create-jira-epic.sh +0 -23
  278. package/pennyfarthing-dist/skills/sprint/scripts/new-sprint.sh +0 -116
  279. package/pennyfarthing-dist/skills/sprint/scripts/promote-epic.sh +0 -164
  280. package/pennyfarthing-dist/skills/sprint/scripts/sprint-info.sh +0 -39
  281. package/pennyfarthing-dist/skills/sprint/scripts/sprint-status.sh +0 -147
  282. package/pennyfarthing-dist/skills/sprint/scripts/sync-epic-jira.sh +0 -23
@@ -1,33 +0,0 @@
1
- #!/bin/bash
2
- # Output sprint info as JSON for Cyclist sidebar
3
- # Usage: .pennyfarthing/scripts/sprint/sprint-info.sh
4
- #
5
- # Returns: {"remaining": N, "inProgress": N, "endDate": "YYYY-MM-DD"}
6
-
7
- set -euo pipefail
8
-
9
- # Find project root
10
- source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
11
-
12
- SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
13
-
14
- if [[ ! -f "$SPRINT_FILE" ]]; then
15
- echo '{"remaining": 0, "inProgress": 0, "endDate": null}'
16
- exit 0
17
- fi
18
-
19
- # Extract end date
20
- END_DATE=$(yq -r '.sprint.end_date // ""' "$SPRINT_FILE")
21
- if [[ -z "$END_DATE" || "$END_DATE" == "null" ]]; then
22
- END_DATE="null"
23
- else
24
- END_DATE="\"$END_DATE\""
25
- fi
26
-
27
- # Calculate remaining points (backlog stories) - use awk for sum since yq add is problematic
28
- REMAINING=$(yq '.epics[].stories[] | select(.status == "backlog" or .status == null) | .points // 0' "$SPRINT_FILE" 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
29
-
30
- # Calculate in-progress points
31
- IN_PROGRESS=$(yq '.epics[].stories[] | select(.status == "in_progress") | .points // 0' "$SPRINT_FILE" 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
32
-
33
- echo "{\"remaining\": $REMAINING, \"inProgress\": $IN_PROGRESS, \"endDate\": $END_DATE}"
@@ -1,230 +0,0 @@
1
- #!/usr/bin/env zsh
2
- # Sprint metrics calculator
3
- # Usage: ./sprint-metrics.sh [--json]
4
- #
5
- # Displays sprint statistics from sprint/current-sprint.yaml:
6
- # - Points burned vs remaining
7
- # - Story completion rates
8
- # - Days remaining in sprint
9
- # - Percentage complete
10
-
11
- set -e
12
-
13
- # Self-locate and set up PROJECT_ROOT
14
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd -P)"
15
- source "$SCRIPT_DIR/../lib/find-root.sh"
16
- SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
17
-
18
- # Colors
19
- RED='\033[0;31m'
20
- GREEN='\033[0;32m'
21
- YELLOW='\033[1;33m'
22
- BLUE='\033[0;34m'
23
- CYAN='\033[0;36m'
24
- MAGENTA='\033[0;35m'
25
- BOLD='\033[1m'
26
- NC='\033[0m'
27
-
28
- # Check for JSON output mode
29
- JSON_MODE=false
30
- for arg in "$@"; do
31
- case $arg in
32
- --json)
33
- JSON_MODE=true
34
- ;;
35
- -h|--help)
36
- cat << 'EOF'
37
- Sprint Metrics - Display current sprint statistics
38
-
39
- Usage: ./sprint-metrics.sh [--json]
40
-
41
- Options:
42
- --json Output in JSON format (for automation)
43
- -h Show this help
44
-
45
- Output includes:
46
- - Sprint number and goal
47
- - Points: completed, in progress, remaining
48
- - Stories: done, in progress, backlog counts
49
- - Days elapsed and remaining
50
- - Percentage complete
51
- - Velocity tracking
52
-
53
- EOF
54
- exit 0
55
- ;;
56
- esac
57
- done
58
-
59
- # Verify sprint file exists
60
- if [[ ! -f "$SPRINT_FILE" ]]; then
61
- echo -e "${RED}❌ Sprint file not found: $SPRINT_FILE${NC}"
62
- exit 1
63
- fi
64
-
65
- # Parse sprint metadata
66
- SPRINT_NUMBER=$(grep -E "^ number:" "$SPRINT_FILE" | head -1 | awk '{print $2}')
67
- SPRINT_GOAL=$(grep -E "^ goal:" "$SPRINT_FILE" | head -1 | sed 's/.*goal: *"//' | sed 's/"$//')
68
- START_DATE=$(grep -E "^ start_date:" "$SPRINT_FILE" | head -1 | awk '{print $2}')
69
- END_DATE=$(grep -E "^ end_date:" "$SPRINT_FILE" | head -1 | awk '{print $2}')
70
-
71
- # Parse summary section
72
- TOTAL_POINTS=$(grep -E "^ total_points:" "$SPRINT_FILE" | awk '{print $2}')
73
- COMPLETED_POINTS=$(grep -E "^ completed_points:" "$SPRINT_FILE" | awk '{print $2}')
74
- IN_PROGRESS_POINTS=$(grep -E "^ in_progress_points:" "$SPRINT_FILE" | awk '{print $2}')
75
- BACKLOG_POINTS=$(grep -E "^ backlog_points:" "$SPRINT_FILE" | awk '{print $2}')
76
- VELOCITY_TARGET=$(grep -E "^ velocity_target:" "$SPRINT_FILE" | awk '{print $2}')
77
-
78
- # Count stories by status
79
- DONE_STORIES=$(grep -E "^\s+status: done" "$SPRINT_FILE" | wc -l | tr -d ' ')
80
- IN_PROGRESS_STORIES=$(grep -E "^\s+status: in.progress" "$SPRINT_FILE" | wc -l | tr -d ' ')
81
- BACKLOG_STORIES=$(grep -E "^\s+status: backlog" "$SPRINT_FILE" | wc -l | tr -d ' ')
82
- TOTAL_STORIES=$((DONE_STORIES + IN_PROGRESS_STORIES + BACKLOG_STORIES))
83
-
84
- # Calculate dates
85
- TODAY=$(date +%Y-%m-%d)
86
- START_EPOCH=$(date -j -f "%Y-%m-%d" "$START_DATE" +%s 2>/dev/null || date -d "$START_DATE" +%s 2>/dev/null)
87
- END_EPOCH=$(date -j -f "%Y-%m-%d" "$END_DATE" +%s 2>/dev/null || date -d "$END_DATE" +%s 2>/dev/null)
88
- TODAY_EPOCH=$(date +%s)
89
-
90
- TOTAL_DAYS=$(( (END_EPOCH - START_EPOCH) / 86400 ))
91
- DAYS_ELAPSED=$(( (TODAY_EPOCH - START_EPOCH) / 86400 ))
92
- DAYS_REMAINING=$(( (END_EPOCH - TODAY_EPOCH) / 86400 ))
93
-
94
- # Ensure non-negative
95
- [[ $DAYS_ELAPSED -lt 0 ]] && DAYS_ELAPSED=0
96
- [[ $DAYS_REMAINING -lt 0 ]] && DAYS_REMAINING=0
97
-
98
- # Calculate percentages
99
- if [[ $TOTAL_POINTS -gt 0 ]]; then
100
- PERCENT_COMPLETE=$(( (COMPLETED_POINTS * 100) / TOTAL_POINTS ))
101
- else
102
- PERCENT_COMPLETE=0
103
- fi
104
-
105
- if [[ $TOTAL_DAYS -gt 0 ]]; then
106
- PERCENT_TIME=$(( (DAYS_ELAPSED * 100) / TOTAL_DAYS ))
107
- else
108
- PERCENT_TIME=0
109
- fi
110
-
111
- # Calculate velocity tracking
112
- EXPECTED_POINTS=0
113
- if [[ $TOTAL_DAYS -gt 0 ]]; then
114
- EXPECTED_POINTS=$(( (VELOCITY_TARGET * DAYS_ELAPSED) / TOTAL_DAYS ))
115
- fi
116
-
117
- # JSON output mode
118
- if [[ "$JSON_MODE" == "true" ]]; then
119
- cat << EOF
120
- {
121
- "sprint": $SPRINT_NUMBER,
122
- "dates": {
123
- "start": "$START_DATE",
124
- "end": "$END_DATE",
125
- "today": "$TODAY"
126
- },
127
- "points": {
128
- "total": $TOTAL_POINTS,
129
- "completed": $COMPLETED_POINTS,
130
- "in_progress": $IN_PROGRESS_POINTS,
131
- "backlog": $BACKLOG_POINTS,
132
- "velocity_target": $VELOCITY_TARGET
133
- },
134
- "stories": {
135
- "total": $TOTAL_STORIES,
136
- "done": $DONE_STORIES,
137
- "in_progress": $IN_PROGRESS_STORIES,
138
- "backlog": $BACKLOG_STORIES
139
- },
140
- "progress": {
141
- "percent_complete": $PERCENT_COMPLETE,
142
- "percent_time": $PERCENT_TIME,
143
- "days_elapsed": $DAYS_ELAPSED,
144
- "days_remaining": $DAYS_REMAINING,
145
- "total_days": $TOTAL_DAYS
146
- },
147
- "velocity": {
148
- "expected_points": $EXPECTED_POINTS,
149
- "actual_points": $COMPLETED_POINTS,
150
- "on_track": $([ $COMPLETED_POINTS -ge $EXPECTED_POINTS ] && echo "true" || echo "false")
151
- }
152
- }
153
- EOF
154
- exit 0
155
- fi
156
-
157
- # Human-readable output
158
- echo ""
159
- echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
160
- echo -e "${BLUE} Sprint $SPRINT_NUMBER Metrics${NC}"
161
- echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
162
-
163
- echo ""
164
- echo -e "${BOLD}📋 Goal:${NC} $SPRINT_GOAL"
165
-
166
- echo ""
167
- echo -e "${BOLD}📅 Timeline${NC}"
168
- echo -e " Start: ${CYAN}$START_DATE${NC}"
169
- echo -e " End: ${CYAN}$END_DATE${NC}"
170
- echo -e " Today: ${CYAN}$TODAY${NC} (Day $DAYS_ELAPSED of $TOTAL_DAYS)"
171
- if [[ $DAYS_REMAINING -gt 0 ]]; then
172
- echo -e " Remaining: ${GREEN}$DAYS_REMAINING days${NC}"
173
- else
174
- echo -e " Remaining: ${RED}Sprint ended${NC}"
175
- fi
176
-
177
- echo ""
178
- echo -e "${BOLD}📊 Points${NC}"
179
- printf " Completed: ${GREEN}%3d${NC} pts\n" "$COMPLETED_POINTS"
180
- printf " In Progress: ${YELLOW}%3d${NC} pts\n" "$IN_PROGRESS_POINTS"
181
- printf " Backlog: ${CYAN}%3d${NC} pts\n" "$BACKLOG_POINTS"
182
- echo -e " ─────────────────"
183
- printf " Total: ${BOLD}%3d${NC} pts\n" "$TOTAL_POINTS"
184
-
185
- echo ""
186
- echo -e "${BOLD}📈 Stories${NC}"
187
- printf " Done: ${GREEN}%3d${NC}\n" "$DONE_STORIES"
188
- printf " In Progress: ${YELLOW}%3d${NC}\n" "$IN_PROGRESS_STORIES"
189
- printf " Backlog: ${CYAN}%3d${NC}\n" "$BACKLOG_STORIES"
190
- echo -e " ─────────────────"
191
- printf " Total: ${BOLD}%3d${NC}\n" "$TOTAL_STORIES"
192
-
193
- echo ""
194
- echo -e "${BOLD}🎯 Progress${NC}"
195
-
196
- # Progress bar for points
197
- BAR_WIDTH=20
198
- FILLED=$(( (PERCENT_COMPLETE * BAR_WIDTH) / 100 ))
199
- EMPTY=$((BAR_WIDTH - FILLED))
200
- BAR=""
201
- for ((i=0; i<FILLED; i++)); do BAR+="█"; done
202
- for ((i=0; i<EMPTY; i++)); do BAR+="░"; done
203
-
204
- echo -e " Points: [${GREEN}${BAR}${NC}] ${PERCENT_COMPLETE}%"
205
-
206
- # Progress bar for time
207
- TIME_FILLED=$(( (PERCENT_TIME * BAR_WIDTH) / 100 ))
208
- TIME_EMPTY=$((BAR_WIDTH - TIME_FILLED))
209
- TIME_BAR=""
210
- for ((i=0; i<TIME_FILLED; i++)); do TIME_BAR+="█"; done
211
- for ((i=0; i<TIME_EMPTY; i++)); do TIME_BAR+="░"; done
212
-
213
- echo -e " Time: [${CYAN}${TIME_BAR}${NC}] ${PERCENT_TIME}%"
214
-
215
- echo ""
216
- echo -e "${BOLD}🏃 Velocity${NC}"
217
- echo -e " Target: ${CYAN}$VELOCITY_TARGET${NC} pts/sprint"
218
- echo -e " Expected: ${CYAN}$EXPECTED_POINTS${NC} pts by now"
219
- echo -e " Actual: ${GREEN}$COMPLETED_POINTS${NC} pts completed"
220
-
221
- if [[ $COMPLETED_POINTS -ge $EXPECTED_POINTS ]]; then
222
- echo -e " Status: ${GREEN}✅ On track${NC}"
223
- elif [[ $COMPLETED_POINTS -ge $((EXPECTED_POINTS - 2)) ]]; then
224
- echo -e " Status: ${YELLOW}⚠️ Slightly behind${NC}"
225
- else
226
- echo -e " Status: ${RED}❌ Behind schedule${NC}"
227
- fi
228
-
229
- echo ""
230
- echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
@@ -1,134 +0,0 @@
1
- #!/bin/bash
2
- # Display current sprint status
3
- # Usage: .pennyfarthing/scripts/sprint/sprint-status.sh [filter]
4
- #
5
- # Filters:
6
- # (none) - Show all stories
7
- # todo - Show only backlog stories
8
- # in-progress - Show only in_progress stories
9
- # done - Show only done/cancelled stories
10
-
11
- set -euo pipefail
12
-
13
- # Self-locate and set up PROJECT_ROOT
14
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
15
- source "$SCRIPT_DIR/../lib/find-root.sh"
16
- source "$SCRIPT_DIR/sprint-common.sh"
17
-
18
- # Parse filter argument
19
- FILTER="${1:-}"
20
- case "$FILTER" in
21
- todo|backlog)
22
- STATUS_FILTER="backlog"
23
- FILTER_LABEL="Todo"
24
- ;;
25
- in-progress|wip)
26
- STATUS_FILTER="in_progress"
27
- FILTER_LABEL="In Progress"
28
- ;;
29
- done|completed)
30
- STATUS_FILTER="done"
31
- FILTER_LABEL="Done"
32
- ;;
33
- cancelled|canceled)
34
- STATUS_FILTER="cancelled"
35
- FILTER_LABEL="Cancelled"
36
- ;;
37
- "")
38
- STATUS_FILTER=""
39
- FILTER_LABEL=""
40
- ;;
41
- *)
42
- echo "Error: Unknown filter '$FILTER'"
43
- echo "Valid filters: todo, in-progress, done, cancelled"
44
- exit 1
45
- ;;
46
- esac
47
-
48
- SPRINT_FILE=$(get_sprint_file)
49
-
50
- if [[ ! -f "$SPRINT_FILE" ]]; then
51
- echo "Error: Sprint file not found at $SPRINT_FILE"
52
- exit 1
53
- fi
54
-
55
- check_yq || exit 1
56
-
57
- # Extract sprint metadata using shared function pattern
58
- SPRINT_NUM=$(get_sprint_metadata "number")
59
- SPRINT_NAME="TO Sprint $SPRINT_NUM"
60
- SPRINT_GOAL=$(get_sprint_metadata "goal")
61
- START_DATE=$(get_sprint_metadata "start_date")
62
- END_DATE=$(get_sprint_metadata "end_date")
63
- STATUS=$(get_sprint_metadata "status")
64
-
65
- echo "# Sprint Status"
66
- echo ""
67
- echo "**Sprint:** $SPRINT_NAME"
68
- echo "**Goal:** $SPRINT_GOAL"
69
- echo "**Dates:** $START_DATE to $END_DATE"
70
- echo "**Status:** $STATUS"
71
- echo ""
72
-
73
- # Get counts using shared functions
74
- STORY_COUNTS=$(get_story_counts)
75
- BACKLOG=$(echo "$STORY_COUNTS" | grep -o 'backlog:[0-9]*' | cut -d: -f2)
76
- IN_PROGRESS=$(echo "$STORY_COUNTS" | grep -o 'in_progress:[0-9]*' | cut -d: -f2)
77
- TOTAL_STORIES=$((BACKLOG + IN_PROGRESS))
78
-
79
- POINT_COUNTS=$(get_point_counts)
80
- BACKLOG_POINTS=$(echo "$POINT_COUNTS" | grep -o 'backlog:[0-9]*' | cut -d: -f2)
81
- IN_PROGRESS_POINTS=$(echo "$POINT_COUNTS" | grep -o 'in_progress:[0-9]*' | cut -d: -f2)
82
- TOTAL_POINTS=$(echo "$POINT_COUNTS" | grep -o 'total:[0-9]*' | cut -d: -f2)
83
-
84
- echo "## Summary"
85
- echo ""
86
- echo "| Status | Stories | Points |"
87
- echo "|--------|---------|--------|"
88
- echo "| Backlog | $BACKLOG | $BACKLOG_POINTS |"
89
- echo "| In Progress | $IN_PROGRESS | $IN_PROGRESS_POINTS |"
90
- echo "| **Total Remaining** | **$TOTAL_STORIES** | **$TOTAL_POINTS** |"
91
- echo ""
92
-
93
- # List stories by epic (grouped - epic name appears once)
94
- if [[ -n "$FILTER_LABEL" ]]; then
95
- echo "## Stories by Epic (${FILTER_LABEL} only)"
96
- else
97
- echo "## Stories by Epic"
98
- fi
99
- echo ""
100
-
101
- # Process each epic, output header once then all its stories
102
- # Apply status filter if specified
103
- if [[ -n "$STATUS_FILTER" ]]; then
104
- yq eval -o=json '.epics[]' "$SPRINT_FILE" 2>/dev/null | jq -r --arg status "$STATUS_FILTER" '
105
- .title as $title |
106
- [.stories[] | select(.status == $status)] |
107
- if length > 0 then
108
- "### " + $title + "\n" +
109
- (map("- [" + .status + "] " + .id + ": " + .title + " (" + (.points | tostring) + " pts)") | join("\n")) + "\n"
110
- else
111
- empty
112
- end
113
- ' 2>/dev/null || echo "No stories found"
114
- else
115
- yq eval -o=json '.epics[]' "$SPRINT_FILE" 2>/dev/null | jq -r '
116
- "### " + .title + "\n" +
117
- (.stories | map("- [" + .status + "] " + .id + ": " + .title + " (" + (.points | tostring) + " pts)") | join("\n")) + "\n"
118
- ' 2>/dev/null || echo "No stories found"
119
- fi
120
-
121
- # Check archive for completed count
122
- SPRINT_NUM=$(echo "$SPRINT_NAME" | sed 's/TO Sprint //')
123
- ARCHIVE_FILE="$PROJECT_ROOT/sprint/archive/sprint-${SPRINT_NUM}-completed.yaml"
124
-
125
- if [[ -f "$ARCHIVE_FILE" ]]; then
126
- COMPLETED_COUNT=$(yq '.completed | length' "$ARCHIVE_FILE" 2>/dev/null || echo "0")
127
- COMPLETED_POINTS=$(sum_points "$(yq '.completed[].points' "$ARCHIVE_FILE" 2>/dev/null)")
128
- echo ""
129
- echo "## Completed This Sprint"
130
- echo ""
131
- echo "**Stories:** $COMPLETED_COUNT | **Points:** $COMPLETED_POINTS"
132
- echo ""
133
- echo "See: sprint/archive/sprint-${SPRINT_NUM}-completed.yaml"
134
- fi
@@ -1,139 +0,0 @@
1
- #!/usr/bin/env zsh
2
- # validate-sprint-yaml.sh - Validate sprint YAML files for common issues
3
- #
4
- # Story MSSCI-14192 - Sprint panel YAML parsing fix
5
- #
6
- # Usage:
7
- # validate-sprint-yaml.sh [path/to/sprint/current-sprint.yaml]
8
- #
9
- # If no path provided, looks for sprint/current-sprint.yaml in current directory.
10
- #
11
- # Common issues detected:
12
- # - YAML syntax errors (including single-quoted strings with blank lines)
13
- # - Missing required fields
14
-
15
- set -euo pipefail
16
-
17
- # Colors for output
18
- RED='\033[0;31m'
19
- GREEN='\033[0;32m'
20
- YELLOW='\033[0;33m'
21
- NC='\033[0m' # No Color
22
-
23
- # Find sprint YAML file
24
- SPRINT_FILE="${1:-sprint/current-sprint.yaml}"
25
-
26
- if [[ ! -f "$SPRINT_FILE" ]]; then
27
- echo -e "${RED}ERROR:${NC} Sprint file not found: $SPRINT_FILE"
28
- exit 1
29
- fi
30
-
31
- echo "Validating: $SPRINT_FILE"
32
- echo ""
33
-
34
- # Track errors
35
- ERRORS=0
36
-
37
- # Main validation using node
38
- validate_yaml() {
39
- local file="$1"
40
-
41
- if ! command -v node &> /dev/null; then
42
- echo -e "${YELLOW}WARNING:${NC} node not available for YAML validation"
43
- return 0
44
- fi
45
-
46
- local result
47
- result=$(node -e "
48
- const { readFileSync } = require('fs');
49
- const { parse } = require('yaml');
50
-
51
- const file = '$file';
52
-
53
- try {
54
- const content = readFileSync(file, 'utf-8');
55
- const data = parse(content);
56
-
57
- // Check for sprint section
58
- if (!data.sprint) {
59
- console.log('WARN:Missing sprint section');
60
- }
61
-
62
- // Check for epics array
63
- if (!Array.isArray(data.epics)) {
64
- console.log('ERROR:epics is not an array or missing');
65
- } else if (data.epics.length === 0) {
66
- console.log('WARN:No epics found in sprint');
67
- } else {
68
- // Count epics and stories
69
- let storyCount = 0;
70
- data.epics.forEach((epic, i) => {
71
- if (!epic.id) console.log('WARN:Epic ' + i + ' missing id');
72
- if (!epic.title) console.log('WARN:Epic ' + i + ' missing title');
73
- if (Array.isArray(epic.stories)) {
74
- storyCount += epic.stories.length;
75
- }
76
- });
77
- console.log('INFO:Found ' + data.epics.length + ' epic(s) with ' + storyCount + ' total stories');
78
- }
79
-
80
- console.log('SUCCESS');
81
- } catch (err) {
82
- const line = err.linePos?.[0]?.line || '?';
83
- console.log('PARSE_ERROR:' + line + ':' + err.message);
84
-
85
- // Provide hint for common single-quote issue
86
- if (err.message && err.message.includes('quote')) {
87
- console.log('HINT:Single-quoted YAML strings cannot contain blank lines. Use literal block scalar (|) instead.');
88
- }
89
- }
90
- " 2>&1)
91
-
92
- # Process output
93
- local success=false
94
- echo "$result" | while IFS= read -r line; do
95
- case "$line" in
96
- SUCCESS)
97
- success=true
98
- ;;
99
- PARSE_ERROR:*)
100
- local info="${line#PARSE_ERROR:}"
101
- local line_num="${info%%:*}"
102
- local message="${info#*:}"
103
- echo -e "${RED}ERROR:${NC} YAML syntax error at line $line_num"
104
- echo " $message"
105
- ERRORS=$((ERRORS + 1))
106
- ;;
107
- HINT:*)
108
- echo -e "${YELLOW}TIP:${NC} ${line#HINT:}"
109
- ;;
110
- ERROR:*)
111
- echo -e "${RED}ERROR:${NC} ${line#ERROR:}"
112
- ERRORS=$((ERRORS + 1))
113
- ;;
114
- WARN:*)
115
- echo -e "${YELLOW}WARNING:${NC} ${line#WARN:}"
116
- ;;
117
- INFO:*)
118
- echo -e "${GREEN}✓${NC} ${line#INFO:}"
119
- ;;
120
- esac
121
- done
122
-
123
- # Check exit status from subshell
124
- if echo "$result" | grep -q "^PARSE_ERROR:" || echo "$result" | grep -q "^ERROR:"; then
125
- return 1
126
- fi
127
- return 0
128
- }
129
-
130
- # Run validation
131
- if validate_yaml "$SPRINT_FILE"; then
132
- echo ""
133
- echo -e "${GREEN}✓ Sprint YAML is valid${NC}"
134
- exit 0
135
- else
136
- echo ""
137
- echo -e "${RED}✗ Validation failed${NC}"
138
- exit 1
139
- fi
@@ -1,101 +0,0 @@
1
- #!/bin/bash
2
- # Archive a completed story from current-sprint.yaml to the sprint archive
3
- # Usage: .pennyfarthing/scripts/sprint/archive-story.sh <story-id> [pr-number]
4
- #
5
- # Example: .pennyfarthing/scripts/sprint/archive-story.sh MSSCI-11945 368
6
-
7
- set -euo pipefail
8
-
9
- STORY_ID="${1:-}"
10
- PR_NUMBER="${2:-}"
11
-
12
- if [[ -z "$STORY_ID" ]]; then
13
- echo "Usage: archive-story.sh <story-id> [pr-number]"
14
- echo "Example: archive-story.sh MSSCI-11945 368"
15
- exit 1
16
- fi
17
-
18
- # PROJECT_ROOT should be set by find-root.sh, but find it if not
19
- if [[ -z "${PROJECT_ROOT:-}" ]]; then
20
- d="$PWD"
21
- while [[ ! -d "$d/.claude" ]] && [[ "$d" != "/" ]]; do
22
- d="$(dirname "$d")"
23
- done
24
- PROJECT_ROOT="$d"
25
- fi
26
-
27
- SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
28
-
29
- if [[ ! -f "$SPRINT_FILE" ]]; then
30
- echo "Error: Sprint file not found at $SPRINT_FILE"
31
- exit 1
32
- fi
33
-
34
- # Extract sprint name to determine archive file
35
- SPRINT_NAME=$(grep -E "^\s+name:" "$SPRINT_FILE" | head -1 | sed 's/.*"TO Sprint \([0-9]*\)".*/\1/')
36
- if [[ -z "$SPRINT_NAME" ]]; then
37
- echo "Error: Could not extract sprint name from $SPRINT_FILE"
38
- exit 1
39
- fi
40
-
41
- ARCHIVE_FILE="$PROJECT_ROOT/sprint/archive/sprint-${SPRINT_NAME}-completed.yaml"
42
-
43
- # Check if archive file exists
44
- if [[ ! -f "$ARCHIVE_FILE" ]]; then
45
- echo "Error: Archive file not found at $ARCHIVE_FILE"
46
- echo "Create it first with new-sprint.sh or manually"
47
- exit 1
48
- fi
49
-
50
- # Use yq to extract story data
51
- if ! command -v yq &> /dev/null; then
52
- echo "Error: yq is required but not installed"
53
- echo "Install with: brew install yq"
54
- exit 1
55
- fi
56
-
57
- # Find the story in current sprint
58
- STORY_DATA=$(yq eval ".epics[].stories[] | select(.id == \"$STORY_ID\")" "$SPRINT_FILE")
59
-
60
- if [[ -z "$STORY_DATA" ]]; then
61
- echo "Error: Story $STORY_ID not found in $SPRINT_FILE"
62
- exit 1
63
- fi
64
-
65
- # Extract story fields
66
- TITLE=$(echo "$STORY_DATA" | yq eval '.title' -)
67
- POINTS=$(echo "$STORY_DATA" | yq eval '.points' -)
68
- EPIC_ID=$(yq eval ".epics[] | select(.stories[].id == \"$STORY_ID\") | .id" "$SPRINT_FILE" | head -1)
69
-
70
- # Get today's date
71
- COMPLETED_DATE=$(date +%Y-%m-%d)
72
-
73
- # Build the archive entry
74
- echo ""
75
- echo "Archiving story:"
76
- echo " ID: $STORY_ID"
77
- echo " Title: $TITLE"
78
- echo " Points: $POINTS"
79
- echo " Epic: $EPIC_ID"
80
- echo " Completed: $COMPLETED_DATE"
81
- [[ -n "$PR_NUMBER" ]] && echo " PR: $PR_NUMBER"
82
- echo ""
83
-
84
- # Append to archive file
85
- {
86
- echo " - id: $STORY_ID"
87
- echo " epic: $EPIC_ID"
88
- echo " title: \"$TITLE\""
89
- echo " points: $POINTS"
90
- echo " completed: $COMPLETED_DATE"
91
- [[ -n "$PR_NUMBER" ]] && echo " pr: $PR_NUMBER"
92
- } >> "$ARCHIVE_FILE"
93
-
94
- echo "Added to $ARCHIVE_FILE"
95
-
96
- # Remove from current sprint
97
- echo ""
98
- echo "Now remove the story from $SPRINT_FILE"
99
- echo "Use: yq eval -i 'del(.epics[].stories[] | select(.id == \"$STORY_ID\"))' $SPRINT_FILE"
100
- echo ""
101
- echo "If the epic has no more stories, also remove the epic section."