@pennyfarthing/core 7.9.2 → 7.9.5

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 (538) hide show
  1. package/package.json +2 -2
  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 +180 -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 +284 -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 +7 -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 +178 -0
  27. package/pennyfarthing-dist/commands/close-epic.md +139 -0
  28. package/pennyfarthing-dist/commands/continue-session.md +184 -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 +7 -0
  32. package/pennyfarthing-dist/commands/devops.md +7 -0
  33. package/pennyfarthing-dist/commands/git-cleanup.md +51 -0
  34. package/pennyfarthing-dist/commands/health-check.md +141 -0
  35. package/pennyfarthing-dist/commands/help.md +264 -0
  36. package/pennyfarthing-dist/commands/job-fair.md +102 -0
  37. package/pennyfarthing-dist/commands/list-themes.md +21 -0
  38. package/pennyfarthing-dist/commands/orchestrator.md +7 -0
  39. package/pennyfarthing-dist/commands/parallel-work.md +71 -0
  40. package/pennyfarthing-dist/commands/party-mode.md +77 -0
  41. package/pennyfarthing-dist/commands/permissions.md +193 -0
  42. package/pennyfarthing-dist/commands/pm.md +7 -0
  43. package/pennyfarthing-dist/commands/prime.md +140 -0
  44. package/pennyfarthing-dist/commands/release.md +58 -0
  45. package/pennyfarthing-dist/commands/repo-status.md +49 -0
  46. package/pennyfarthing-dist/commands/retro.md +200 -0
  47. package/pennyfarthing-dist/commands/reviewer.md +7 -0
  48. package/pennyfarthing-dist/commands/run-ci.md +116 -0
  49. package/pennyfarthing-dist/commands/set-theme.md +56 -0
  50. package/pennyfarthing-dist/commands/show-theme.md +21 -0
  51. package/pennyfarthing-dist/commands/sm.md +7 -0
  52. package/pennyfarthing-dist/commands/solo.md +447 -0
  53. package/pennyfarthing-dist/commands/sprint-planning.md +109 -0
  54. package/pennyfarthing-dist/commands/sprint.md +133 -0
  55. package/pennyfarthing-dist/commands/standalone.md +194 -0
  56. package/pennyfarthing-dist/commands/start-epic.md +168 -0
  57. package/pennyfarthing-dist/commands/sync-epic-to-jira.md +184 -0
  58. package/pennyfarthing-dist/commands/sync-work-with-sprint.md +373 -0
  59. package/pennyfarthing-dist/commands/tea.md +7 -0
  60. package/pennyfarthing-dist/commands/tech-writer.md +7 -0
  61. package/pennyfarthing-dist/commands/theme-maker.md +676 -0
  62. package/pennyfarthing-dist/commands/update-domain-docs.md +83 -0
  63. package/pennyfarthing-dist/commands/ux-designer.md +7 -0
  64. package/pennyfarthing-dist/commands/work.md +23 -0
  65. package/pennyfarthing-dist/commands/workflow.md +21 -0
  66. package/pennyfarthing-dist/guides/agent-behavior.md +311 -0
  67. package/pennyfarthing-dist/guides/agent-coordination.md +480 -0
  68. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +432 -0
  69. package/pennyfarthing-dist/guides/agent-template-strategic.md +148 -0
  70. package/pennyfarthing-dist/guides/agent-template-tactical.md +162 -0
  71. package/pennyfarthing-dist/guides/hooks.md +230 -0
  72. package/pennyfarthing-dist/guides/measurement-framework.md +210 -0
  73. package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +766 -0
  74. package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +574 -0
  75. package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +488 -0
  76. package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +402 -0
  77. package/pennyfarthing-dist/guides/permission-protocol.md +188 -0
  78. package/pennyfarthing-dist/guides/persona-loading.md +46 -0
  79. package/pennyfarthing-dist/guides/prompt-patterns.md +338 -0
  80. package/pennyfarthing-dist/guides/scale-levels.md +114 -0
  81. package/pennyfarthing-dist/guides/session-artifacts.md +193 -0
  82. package/pennyfarthing-dist/guides/workflow-schema.md +257 -0
  83. package/pennyfarthing-dist/guides/worktree-mode.md +113 -0
  84. package/pennyfarthing-dist/guides/xml-tags.md +335 -0
  85. package/pennyfarthing-dist/output-styles/teaching.md +33 -0
  86. package/pennyfarthing-dist/output-styles/terse.md +20 -0
  87. package/pennyfarthing-dist/output-styles/verbose.md +28 -0
  88. package/pennyfarthing-dist/personas/BENCHMARK-METHODOLOGY.md +105 -0
  89. package/pennyfarthing-dist/personas/OCEAN-BENCHMARKING.md +210 -0
  90. package/pennyfarthing-dist/personas/TRAIL-OCEAN-MAPPING.md +168 -0
  91. package/pennyfarthing-dist/personas/ZEITGEIST-ANALYSIS.md +171 -0
  92. package/pennyfarthing-dist/personas/attributes.yaml +69 -0
  93. package/pennyfarthing-dist/personas/scripts/add-zeitgeist-calibrated.py +81 -0
  94. package/pennyfarthing-dist/personas/scripts/add-zeitgeist-scores.sh +56 -0
  95. package/pennyfarthing-dist/personas/themes/1984.yaml +304 -0
  96. package/pennyfarthing-dist/personas/themes/a-team.yaml +331 -0
  97. package/pennyfarthing-dist/personas/themes/agatha-christie.yaml +294 -0
  98. package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +324 -0
  99. package/pennyfarthing-dist/personas/themes/all-stars.yaml +326 -0
  100. package/pennyfarthing-dist/personas/themes/ancient-philosophers.yaml +312 -0
  101. package/pennyfarthing-dist/personas/themes/ancient-strategists.yaml +298 -0
  102. package/pennyfarthing-dist/personas/themes/arcane.yaml +282 -0
  103. package/pennyfarthing-dist/personas/themes/arthurian-mythos.yaml +327 -0
  104. package/pennyfarthing-dist/personas/themes/avatar-the-last-airbender.yaml +282 -0
  105. package/pennyfarthing-dist/personas/themes/babylon-5.yaml +282 -0
  106. package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +282 -0
  107. package/pennyfarthing-dist/personas/themes/better-call-saul.yaml +282 -0
  108. package/pennyfarthing-dist/personas/themes/big-lebowski.yaml +294 -0
  109. package/pennyfarthing-dist/personas/themes/black-sails.yaml +294 -0
  110. package/pennyfarthing-dist/personas/themes/blade-runner.yaml +289 -0
  111. package/pennyfarthing-dist/personas/themes/bobiverse.yaml +282 -0
  112. package/pennyfarthing-dist/personas/themes/breaking-bad.yaml +319 -0
  113. package/pennyfarthing-dist/personas/themes/catch-22.yaml +304 -0
  114. package/pennyfarthing-dist/personas/themes/classical-composers.yaml +302 -0
  115. package/pennyfarthing-dist/personas/themes/control.yaml +201 -0
  116. package/pennyfarthing-dist/personas/themes/count-of-monte-cristo.yaml +312 -0
  117. package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +315 -0
  118. package/pennyfarthing-dist/personas/themes/deadwood.yaml +294 -0
  119. package/pennyfarthing-dist/personas/themes/dickens.yaml +312 -0
  120. package/pennyfarthing-dist/personas/themes/discworld.yaml +334 -0
  121. package/pennyfarthing-dist/personas/themes/doctor-who.yaml +284 -0
  122. package/pennyfarthing-dist/personas/themes/don-quixote.yaml +312 -0
  123. package/pennyfarthing-dist/personas/themes/dune.yaml +301 -0
  124. package/pennyfarthing-dist/personas/themes/enlightenment-thinkers.yaml +312 -0
  125. package/pennyfarthing-dist/personas/themes/expeditionary-force.yaml +282 -0
  126. package/pennyfarthing-dist/personas/themes/fargo.yaml +322 -0
  127. package/pennyfarthing-dist/personas/themes/film-auteurs.yaml +304 -0
  128. package/pennyfarthing-dist/personas/themes/firefly.yaml +320 -0
  129. package/pennyfarthing-dist/personas/themes/foundation.yaml +284 -0
  130. package/pennyfarthing-dist/personas/themes/futurama.yaml +313 -0
  131. package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +284 -0
  132. package/pennyfarthing-dist/personas/themes/gilligans-island.yaml +365 -0
  133. package/pennyfarthing-dist/personas/themes/gothic-literature.yaml +300 -0
  134. package/pennyfarthing-dist/personas/themes/great-gatsby.yaml +300 -0
  135. package/pennyfarthing-dist/personas/themes/greek-mythology.yaml +326 -0
  136. package/pennyfarthing-dist/personas/themes/hannibal.yaml +294 -0
  137. package/pennyfarthing-dist/personas/themes/harry-potter.yaml +316 -0
  138. package/pennyfarthing-dist/personas/themes/his-dark-materials.yaml +285 -0
  139. package/pennyfarthing-dist/personas/themes/historical-figures.yaml +282 -0
  140. package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +323 -0
  141. package/pennyfarthing-dist/personas/themes/house-md.yaml +313 -0
  142. package/pennyfarthing-dist/personas/themes/imperial-radch.yaml +283 -0
  143. package/pennyfarthing-dist/personas/themes/inspector-morse.yaml +294 -0
  144. package/pennyfarthing-dist/personas/themes/jane-austen.yaml +281 -0
  145. package/pennyfarthing-dist/personas/themes/jazz-legends.yaml +312 -0
  146. package/pennyfarthing-dist/personas/themes/justified.yaml +294 -0
  147. package/pennyfarthing-dist/personas/themes/legion-of-doom.yaml +343 -0
  148. package/pennyfarthing-dist/personas/themes/les-miserables.yaml +293 -0
  149. package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +326 -0
  150. package/pennyfarthing-dist/personas/themes/lovecraft-mythos.yaml +325 -0
  151. package/pennyfarthing-dist/personas/themes/mad-max.yaml +349 -0
  152. package/pennyfarthing-dist/personas/themes/mad-men.yaml +283 -0
  153. package/pennyfarthing-dist/personas/themes/marvel-mcu.yaml +294 -0
  154. package/pennyfarthing-dist/personas/themes/mash.yaml +329 -0
  155. package/pennyfarthing-dist/personas/themes/mass-effect.yaml +283 -0
  156. package/pennyfarthing-dist/personas/themes/military-commanders.yaml +298 -0
  157. package/pennyfarthing-dist/personas/themes/moby-dick.yaml +312 -0
  158. package/pennyfarthing-dist/personas/themes/monty-python.yaml +297 -0
  159. package/pennyfarthing-dist/personas/themes/neuromancer.yaml +294 -0
  160. package/pennyfarthing-dist/personas/themes/norse-mythology.yaml +321 -0
  161. package/pennyfarthing-dist/personas/themes/parks-and-rec.yaml +364 -0
  162. package/pennyfarthing-dist/personas/themes/peaky-blinders.yaml +292 -0
  163. package/pennyfarthing-dist/personas/themes/princess-bride.yaml +344 -0
  164. package/pennyfarthing-dist/personas/themes/renaissance-masters.yaml +312 -0
  165. package/pennyfarthing-dist/personas/themes/rome.yaml +294 -0
  166. package/pennyfarthing-dist/personas/themes/russian-masters.yaml +310 -0
  167. package/pennyfarthing-dist/personas/themes/sandman.yaml +282 -0
  168. package/pennyfarthing-dist/personas/themes/scientific-revolutionaries.yaml +312 -0
  169. package/pennyfarthing-dist/personas/themes/shakespeare.yaml +295 -0
  170. package/pennyfarthing-dist/personas/themes/sherlock-holmes.yaml +283 -0
  171. package/pennyfarthing-dist/personas/themes/snow-crash.yaml +290 -0
  172. package/pennyfarthing-dist/personas/themes/software-pioneers.yaml +294 -0
  173. package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +358 -0
  174. package/pennyfarthing-dist/personas/themes/star-trek-tos.yaml +327 -0
  175. package/pennyfarthing-dist/personas/themes/star-wars.yaml +297 -0
  176. package/pennyfarthing-dist/personas/themes/succession.yaml +294 -0
  177. package/pennyfarthing-dist/personas/themes/superfriends.yaml +332 -0
  178. package/pennyfarthing-dist/personas/themes/ted-lasso.yaml +359 -0
  179. package/pennyfarthing-dist/personas/themes/the-americans.yaml +294 -0
  180. package/pennyfarthing-dist/personas/themes/the-crown.yaml +294 -0
  181. package/pennyfarthing-dist/personas/themes/the-expanse.yaml +337 -0
  182. package/pennyfarthing-dist/personas/themes/the-good-place.yaml +315 -0
  183. package/pennyfarthing-dist/personas/themes/the-matrix.yaml +342 -0
  184. package/pennyfarthing-dist/personas/themes/the-odyssey.yaml +294 -0
  185. package/pennyfarthing-dist/personas/themes/the-office.yaml +323 -0
  186. package/pennyfarthing-dist/personas/themes/the-simpsons.yaml +300 -0
  187. package/pennyfarthing-dist/personas/themes/the-sopranos.yaml +294 -0
  188. package/pennyfarthing-dist/personas/themes/the-wire.yaml +303 -0
  189. package/pennyfarthing-dist/personas/themes/the-witcher.yaml +294 -0
  190. package/pennyfarthing-dist/personas/themes/twin-peaks.yaml +296 -0
  191. package/pennyfarthing-dist/personas/themes/vorkosigan-saga.yaml +294 -0
  192. package/pennyfarthing-dist/personas/themes/watchmen.yaml +285 -0
  193. package/pennyfarthing-dist/personas/themes/west-wing.yaml +285 -0
  194. package/pennyfarthing-dist/personas/themes/world-explorers.yaml +312 -0
  195. package/pennyfarthing-dist/personas/themes/wwii-leaders.yaml +299 -0
  196. package/pennyfarthing-dist/personas/themes/x-files.yaml +296 -0
  197. package/pennyfarthing-dist/personas/zeitgeist-scores.yaml +1172 -0
  198. package/pennyfarthing-dist/scripts/README.md +87 -0
  199. package/pennyfarthing-dist/scripts/core/README.md +26 -0
  200. package/pennyfarthing-dist/scripts/core/agent-session.sh +383 -0
  201. package/pennyfarthing-dist/scripts/core/check-context.sh +280 -0
  202. package/pennyfarthing-dist/scripts/core/handoff-marker.sh +101 -0
  203. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +95 -0
  204. package/pennyfarthing-dist/scripts/core/prime.sh +30 -0
  205. package/pennyfarthing-dist/scripts/core/run.sh +92 -0
  206. package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +21 -0
  207. package/pennyfarthing-dist/scripts/git/README.md +25 -0
  208. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +267 -0
  209. package/pennyfarthing-dist/scripts/git/git-status-all.sh +152 -0
  210. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +91 -0
  211. package/pennyfarthing-dist/scripts/git/release.sh +215 -0
  212. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +494 -0
  213. package/pennyfarthing-dist/scripts/health/drift-detection.sh +162 -0
  214. package/pennyfarthing-dist/scripts/hooks/README.md +32 -0
  215. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +106 -0
  216. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +60 -0
  217. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +65 -0
  218. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +35 -0
  219. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +166 -0
  220. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +107 -0
  221. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +71 -0
  222. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +54 -0
  223. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +20 -0
  224. package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +499 -0
  225. package/pennyfarthing-dist/scripts/hooks/session-start.sh +97 -0
  226. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +65 -0
  227. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +94 -0
  228. package/pennyfarthing-dist/scripts/jira/README.md +36 -0
  229. package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +101 -0
  230. package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +97 -0
  231. package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +22 -0
  232. package/pennyfarthing-dist/scripts/jira/jira-lib.sh +464 -0
  233. package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +266 -0
  234. package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +18 -0
  235. package/pennyfarthing-dist/scripts/jira/jira-sync.sh +16 -0
  236. package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +16 -0
  237. package/pennyfarthing-dist/scripts/jira/sync-epic-to-jira.sh +16 -0
  238. package/pennyfarthing-dist/scripts/lib/README.md +29 -0
  239. package/pennyfarthing-dist/scripts/lib/background-tasks.sh +177 -0
  240. package/pennyfarthing-dist/scripts/lib/checkpoint.sh +136 -0
  241. package/pennyfarthing-dist/scripts/lib/common.sh +212 -0
  242. package/pennyfarthing-dist/scripts/lib/file-lock.sh +269 -0
  243. package/pennyfarthing-dist/scripts/lib/find-root.sh +35 -0
  244. package/pennyfarthing-dist/scripts/lib/logging.sh +186 -0
  245. package/pennyfarthing-dist/scripts/lib/retry.sh +76 -0
  246. package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +102 -0
  247. package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +97 -0
  248. package/pennyfarthing-dist/scripts/misc/README.md +44 -0
  249. package/pennyfarthing-dist/scripts/misc/add-short-names.sh +13 -0
  250. package/pennyfarthing-dist/scripts/misc/add_short_names.py +226 -0
  251. package/pennyfarthing-dist/scripts/misc/backlog.sh +91 -0
  252. package/pennyfarthing-dist/scripts/misc/check-status.sh +247 -0
  253. package/pennyfarthing-dist/scripts/misc/find-related-work.sh +231 -0
  254. package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +122 -0
  255. package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +74 -0
  256. package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +10 -0
  257. package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +319 -0
  258. package/pennyfarthing-dist/scripts/misc/repo-scan.sh +141 -0
  259. package/pennyfarthing-dist/scripts/misc/repo-utils.sh +778 -0
  260. package/pennyfarthing-dist/scripts/misc/run-ci.sh +219 -0
  261. package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +7 -0
  262. package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +319 -0
  263. package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +193 -0
  264. package/pennyfarthing-dist/scripts/misc/statusline.sh +259 -0
  265. package/pennyfarthing-dist/scripts/misc/uninstall.sh +270 -0
  266. package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +160 -0
  267. package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +400 -0
  268. package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +54 -0
  269. package/pennyfarthing-dist/scripts/sprint/README.md +29 -0
  270. package/pennyfarthing-dist/scripts/sprint/archive-story.sh +139 -0
  271. package/pennyfarthing-dist/scripts/sprint/available-stories.sh +97 -0
  272. package/pennyfarthing-dist/scripts/sprint/check-story.sh +164 -0
  273. package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +58 -0
  274. package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +69 -0
  275. package/pennyfarthing-dist/scripts/sprint/import-epic-to-future.sh +10 -0
  276. package/pennyfarthing-dist/scripts/sprint/import_epic_to_future.py +270 -0
  277. package/pennyfarthing-dist/scripts/sprint/list-future.sh +151 -0
  278. package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +116 -0
  279. package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +154 -0
  280. package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +421 -0
  281. package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +39 -0
  282. package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +241 -0
  283. package/pennyfarthing-dist/scripts/sprint/sprint-status.sh +134 -0
  284. package/pennyfarthing-dist/scripts/story/README.md +23 -0
  285. package/pennyfarthing-dist/scripts/story/create-story.sh +19 -0
  286. package/pennyfarthing-dist/scripts/story/size-story.sh +18 -0
  287. package/pennyfarthing-dist/scripts/story/story-template.sh +18 -0
  288. package/pennyfarthing-dist/scripts/test/README.md +23 -0
  289. package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +59 -0
  290. package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +220 -0
  291. package/pennyfarthing-dist/scripts/test/swebench-judge.py +374 -0
  292. package/pennyfarthing-dist/scripts/test/test-cache.sh +165 -0
  293. package/pennyfarthing-dist/scripts/test/test-setup.sh +337 -0
  294. package/pennyfarthing-dist/scripts/tests/check.test.sh +582 -0
  295. package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +515 -0
  296. package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +599 -0
  297. package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +332 -0
  298. package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +573 -0
  299. package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +859 -0
  300. package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +662 -0
  301. package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +589 -0
  302. package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +105 -0
  303. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +597 -0
  304. package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +514 -0
  305. package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +517 -0
  306. package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +331 -0
  307. package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +647 -0
  308. package/pennyfarthing-dist/scripts/theme/README.md +22 -0
  309. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +13 -0
  310. package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +402 -0
  311. package/pennyfarthing-dist/scripts/theme/list-themes.sh +73 -0
  312. package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +97 -0
  313. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +576 -0
  314. package/pennyfarthing-dist/scripts/workflow/README.md +28 -0
  315. package/pennyfarthing-dist/scripts/workflow/check.py +502 -0
  316. package/pennyfarthing-dist/scripts/workflow/check.sh +24 -0
  317. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +159 -0
  318. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +228 -0
  319. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +61 -0
  320. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +13 -0
  321. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +130 -0
  322. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +40 -0
  323. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +163 -0
  324. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +138 -0
  325. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +256 -0
  326. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +167 -0
  327. package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +242 -0
  328. package/pennyfarthing-dist/skills/changelog/SKILL.md +367 -0
  329. package/pennyfarthing-dist/skills/code-review/SKILL.md +168 -0
  330. package/pennyfarthing-dist/skills/context-engineering/SKILL.md +274 -0
  331. package/pennyfarthing-dist/skills/cyclist/SKILL.md +88 -0
  332. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +437 -0
  333. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +258 -0
  334. package/pennyfarthing-dist/skills/jira/SKILL.md +484 -0
  335. package/pennyfarthing-dist/skills/judge/SKILL.md +636 -0
  336. package/pennyfarthing-dist/skills/just/SKILL.md +403 -0
  337. package/pennyfarthing-dist/skills/mermaid/SKILL.md +240 -0
  338. package/pennyfarthing-dist/skills/otel/skill.md +223 -0
  339. package/pennyfarthing-dist/skills/permissions/skill.md +172 -0
  340. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +178 -0
  341. package/pennyfarthing-dist/skills/skill-registry.schema.json +107 -0
  342. package/pennyfarthing-dist/skills/skill-registry.yaml +393 -0
  343. package/pennyfarthing-dist/skills/sprint/scripts/archive-story.sh +101 -0
  344. package/pennyfarthing-dist/skills/sprint/scripts/available-stories.sh +97 -0
  345. package/pennyfarthing-dist/skills/sprint/scripts/check-story.sh +164 -0
  346. package/pennyfarthing-dist/skills/sprint/scripts/create-jira-epic.sh +101 -0
  347. package/pennyfarthing-dist/skills/sprint/scripts/new-sprint.sh +116 -0
  348. package/pennyfarthing-dist/skills/sprint/scripts/promote-epic.sh +164 -0
  349. package/pennyfarthing-dist/skills/sprint/scripts/sprint-info.sh +39 -0
  350. package/pennyfarthing-dist/skills/sprint/scripts/sprint-status.sh +147 -0
  351. package/pennyfarthing-dist/skills/sprint/scripts/sync-epic-jira.sh +86 -0
  352. package/pennyfarthing-dist/skills/sprint/skill.md +465 -0
  353. package/pennyfarthing-dist/skills/story/scripts/create-story.sh +159 -0
  354. package/pennyfarthing-dist/skills/story/scripts/size-story.sh +198 -0
  355. package/pennyfarthing-dist/skills/story/scripts/story-template.sh +162 -0
  356. package/pennyfarthing-dist/skills/story/skill.md +219 -0
  357. package/pennyfarthing-dist/skills/systematic-debugging/SKILL.md +390 -0
  358. package/pennyfarthing-dist/skills/testing/SKILL.md +99 -0
  359. package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +124 -0
  360. package/pennyfarthing-dist/skills/theme/skill.md +129 -0
  361. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +174 -0
  362. package/pennyfarthing-dist/skills/workflow/scripts/list-workflows.sh +91 -0
  363. package/pennyfarthing-dist/skills/workflow/scripts/resume-workflow.sh +163 -0
  364. package/pennyfarthing-dist/skills/workflow/scripts/show-workflow.sh +138 -0
  365. package/pennyfarthing-dist/skills/workflow/scripts/start-workflow.sh +273 -0
  366. package/pennyfarthing-dist/skills/workflow/scripts/workflow-status.sh +167 -0
  367. package/pennyfarthing-dist/skills/workflow/skill.md +337 -0
  368. package/pennyfarthing-dist/skills/yq/SKILL.md +264 -0
  369. package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +187 -0
  370. package/pennyfarthing-dist/templates/LEADERBOARD.template.md +59 -0
  371. package/pennyfarthing-dist/templates/agent-scopes.yaml.template +276 -0
  372. package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +61 -0
  373. package/pennyfarthing-dist/templates/persona-config.yaml.template +22 -0
  374. package/pennyfarthing-dist/templates/preferences.yaml.template +15 -0
  375. package/pennyfarthing-dist/templates/settings.local.json.template +101 -0
  376. package/pennyfarthing-dist/templates/setup-env.sh.template +18 -0
  377. package/pennyfarthing-dist/templates/shared-context.md.template +70 -0
  378. package/pennyfarthing-dist/templates/sidecar/decisions.md.template +40 -0
  379. package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +37 -0
  380. package/pennyfarthing-dist/templates/sidecar/patterns.md.template +34 -0
  381. package/pennyfarthing-dist/workflows/agent-docs.yaml +70 -0
  382. package/pennyfarthing-dist/workflows/architecture/steps/step-01-initialize.md +101 -0
  383. package/pennyfarthing-dist/workflows/architecture/steps/step-01b-continue.md +93 -0
  384. package/pennyfarthing-dist/workflows/architecture/steps/step-02-context.md +115 -0
  385. package/pennyfarthing-dist/workflows/architecture/steps/step-03-patterns.md +133 -0
  386. package/pennyfarthing-dist/workflows/architecture/steps/step-04-components.md +138 -0
  387. package/pennyfarthing-dist/workflows/architecture/steps/step-05-interfaces.md +133 -0
  388. package/pennyfarthing-dist/workflows/architecture/steps/step-06-risks.md +142 -0
  389. package/pennyfarthing-dist/workflows/architecture/steps/step-07-document.md +160 -0
  390. package/pennyfarthing-dist/workflows/architecture/templates/architecture-decision.md +102 -0
  391. package/pennyfarthing-dist/workflows/architecture.yaml +65 -0
  392. package/pennyfarthing-dist/workflows/bdd.yaml +60 -0
  393. package/pennyfarthing-dist/workflows/brainstorming/brain-methods.csv +62 -0
  394. package/pennyfarthing-dist/workflows/brainstorming/checklist.md +44 -0
  395. package/pennyfarthing-dist/workflows/brainstorming/instructions.md +736 -0
  396. package/pennyfarthing-dist/workflows/brainstorming/workflow.yaml +49 -0
  397. package/pennyfarthing-dist/workflows/code-review/checklist.md +23 -0
  398. package/pennyfarthing-dist/workflows/code-review/instructions.md +234 -0
  399. package/pennyfarthing-dist/workflows/code-review/workflow.yaml +51 -0
  400. package/pennyfarthing-dist/workflows/dev-story/checklist.md +80 -0
  401. package/pennyfarthing-dist/workflows/dev-story/instructions.xml +410 -0
  402. package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +50 -0
  403. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-01-validate-prerequisites.md +256 -0
  404. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-02-design-epics.md +233 -0
  405. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-03-create-stories.md +272 -0
  406. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +153 -0
  407. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +122 -0
  408. package/pennyfarthing-dist/workflows/epics-and-stories/templates/epics-template.md +57 -0
  409. package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +28 -0
  410. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +101 -0
  411. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-02-categorize.md +116 -0
  412. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +224 -0
  413. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +88 -0
  414. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +79 -0
  415. package/pennyfarthing-dist/workflows/git-cleanup.yaml +59 -0
  416. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-01-document-discovery.md +190 -0
  417. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-02-prd-analysis.md +178 -0
  418. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-03-epic-coverage-validation.md +179 -0
  419. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-04-ux-alignment.md +139 -0
  420. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-05-epic-quality-review.md +252 -0
  421. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-06-final-assessment.md +133 -0
  422. package/pennyfarthing-dist/workflows/implementation-readiness/templates/readiness-report-template.md +4 -0
  423. package/pennyfarthing-dist/workflows/implementation-readiness/workflow.yaml +40 -0
  424. package/pennyfarthing-dist/workflows/prd/data/domain-complexity.csv +13 -0
  425. package/pennyfarthing-dist/workflows/prd/data/prd-purpose.md +197 -0
  426. package/pennyfarthing-dist/workflows/prd/data/project-types.csv +11 -0
  427. package/pennyfarthing-dist/workflows/prd/steps-c/step-01-init.md +191 -0
  428. package/pennyfarthing-dist/workflows/prd/steps-c/step-01b-continue.md +153 -0
  429. package/pennyfarthing-dist/workflows/prd/steps-c/step-02-discovery.md +224 -0
  430. package/pennyfarthing-dist/workflows/prd/steps-c/step-03-success.md +226 -0
  431. package/pennyfarthing-dist/workflows/prd/steps-c/step-04-journeys.md +213 -0
  432. package/pennyfarthing-dist/workflows/prd/steps-c/step-05-domain.md +207 -0
  433. package/pennyfarthing-dist/workflows/prd/steps-c/step-06-innovation.md +226 -0
  434. package/pennyfarthing-dist/workflows/prd/steps-c/step-07-project-type.md +237 -0
  435. package/pennyfarthing-dist/workflows/prd/steps-c/step-08-scoping.md +228 -0
  436. package/pennyfarthing-dist/workflows/prd/steps-c/step-09-functional.md +231 -0
  437. package/pennyfarthing-dist/workflows/prd/steps-c/step-10-nonfunctional.md +242 -0
  438. package/pennyfarthing-dist/workflows/prd/steps-c/step-11-polish.md +217 -0
  439. package/pennyfarthing-dist/workflows/prd/steps-c/step-12-complete.md +180 -0
  440. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01-discovery.md +247 -0
  441. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01b-legacy-conversion.md +208 -0
  442. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-02-review.md +249 -0
  443. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-03-edit.md +253 -0
  444. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-04-complete.md +168 -0
  445. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-01-discovery.md +218 -0
  446. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02-format-detection.md +191 -0
  447. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02b-parity-check.md +209 -0
  448. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-03-density-validation.md +174 -0
  449. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
  450. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-05-measurability-validation.md +228 -0
  451. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-06-traceability-validation.md +217 -0
  452. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
  453. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
  454. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-09-project-type-validation.md +263 -0
  455. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-10-smart-validation.md +209 -0
  456. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
  457. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-12-completeness-validation.md +242 -0
  458. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-13-report-complete.md +232 -0
  459. package/pennyfarthing-dist/workflows/prd/templates/prd-template.md +10 -0
  460. package/pennyfarthing-dist/workflows/prd/workflow.yaml +42 -0
  461. package/pennyfarthing-dist/workflows/product-brief/steps/step-01-init.md +177 -0
  462. package/pennyfarthing-dist/workflows/product-brief/steps/step-01b-continue.md +161 -0
  463. package/pennyfarthing-dist/workflows/product-brief/steps/step-02-vision.md +199 -0
  464. package/pennyfarthing-dist/workflows/product-brief/steps/step-03-users.md +202 -0
  465. package/pennyfarthing-dist/workflows/product-brief/steps/step-04-metrics.md +205 -0
  466. package/pennyfarthing-dist/workflows/product-brief/steps/step-05-scope.md +219 -0
  467. package/pennyfarthing-dist/workflows/product-brief/steps/step-06-complete.md +194 -0
  468. package/pennyfarthing-dist/workflows/product-brief/templates/product-brief.template.md +10 -0
  469. package/pennyfarthing-dist/workflows/product-brief/workflow.yaml +31 -0
  470. package/pennyfarthing-dist/workflows/project-context/project-context-template.md +21 -0
  471. package/pennyfarthing-dist/workflows/project-context/steps/step-01-discover.md +184 -0
  472. package/pennyfarthing-dist/workflows/project-context/steps/step-02-generate.md +318 -0
  473. package/pennyfarthing-dist/workflows/project-context/steps/step-03-complete.md +278 -0
  474. package/pennyfarthing-dist/workflows/project-context/workflow.yaml +27 -0
  475. package/pennyfarthing-dist/workflows/quick-dev/steps/step-01-mode-detection.md +156 -0
  476. package/pennyfarthing-dist/workflows/quick-dev/steps/step-02-context-gathering.md +120 -0
  477. package/pennyfarthing-dist/workflows/quick-dev/steps/step-03-execute.md +113 -0
  478. package/pennyfarthing-dist/workflows/quick-dev/steps/step-04-self-check.md +113 -0
  479. package/pennyfarthing-dist/workflows/quick-dev/steps/step-05-adversarial-review.md +106 -0
  480. package/pennyfarthing-dist/workflows/quick-dev/steps/step-06-resolve-findings.md +140 -0
  481. package/pennyfarthing-dist/workflows/quick-dev/workflow.yaml +27 -0
  482. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +189 -0
  483. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +144 -0
  484. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +128 -0
  485. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +191 -0
  486. package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +74 -0
  487. package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +27 -0
  488. package/pennyfarthing-dist/workflows/research/steps-domain/step-01-init.md +137 -0
  489. package/pennyfarthing-dist/workflows/research/steps-domain/step-02-domain-analysis.md +229 -0
  490. package/pennyfarthing-dist/workflows/research/steps-domain/step-03-competitive-landscape.md +238 -0
  491. package/pennyfarthing-dist/workflows/research/steps-domain/step-04-regulatory-focus.md +206 -0
  492. package/pennyfarthing-dist/workflows/research/steps-domain/step-05-technical-trends.md +234 -0
  493. package/pennyfarthing-dist/workflows/research/steps-domain/step-06-research-synthesis.md +443 -0
  494. package/pennyfarthing-dist/workflows/research/steps-market/step-01-init.md +182 -0
  495. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-behavior.md +237 -0
  496. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-insights.md +200 -0
  497. package/pennyfarthing-dist/workflows/research/steps-market/step-03-customer-pain-points.md +249 -0
  498. package/pennyfarthing-dist/workflows/research/steps-market/step-04-customer-decisions.md +259 -0
  499. package/pennyfarthing-dist/workflows/research/steps-market/step-05-competitive-analysis.md +177 -0
  500. package/pennyfarthing-dist/workflows/research/steps-market/step-06-research-completion.md +475 -0
  501. package/pennyfarthing-dist/workflows/research/steps-technical/step-01-init.md +137 -0
  502. package/pennyfarthing-dist/workflows/research/steps-technical/step-02-technical-overview.md +239 -0
  503. package/pennyfarthing-dist/workflows/research/steps-technical/step-03-integration-patterns.md +248 -0
  504. package/pennyfarthing-dist/workflows/research/steps-technical/step-04-architectural-patterns.md +202 -0
  505. package/pennyfarthing-dist/workflows/research/steps-technical/step-05-implementation-research.md +239 -0
  506. package/pennyfarthing-dist/workflows/research/steps-technical/step-06-research-synthesis.md +486 -0
  507. package/pennyfarthing-dist/workflows/research/templates/research.template.md +29 -0
  508. package/pennyfarthing-dist/workflows/research/workflow.yaml +45 -0
  509. package/pennyfarthing-dist/workflows/retrospective/checklist.md +31 -0
  510. package/pennyfarthing-dist/workflows/retrospective/instructions.md +1443 -0
  511. package/pennyfarthing-dist/workflows/retrospective/workflow.yaml +50 -0
  512. package/pennyfarthing-dist/workflows/sprint-planning/checklist.md +33 -0
  513. package/pennyfarthing-dist/workflows/sprint-planning/sprint-status-template.yaml +55 -0
  514. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-01-parse-epic-files.md +54 -0
  515. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-02-build-sprint-status.md +44 -0
  516. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-03-status-detection.md +64 -0
  517. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-04-generate-status-file.md +73 -0
  518. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-05-validate-and-report.md +56 -0
  519. package/pennyfarthing-dist/workflows/sprint-planning/workflow.yaml +34 -0
  520. package/pennyfarthing-dist/workflows/tdd.yaml +50 -0
  521. package/pennyfarthing-dist/workflows/trivial.yaml +40 -0
  522. package/pennyfarthing-dist/workflows/ux-design/steps/step-01-init.md +135 -0
  523. package/pennyfarthing-dist/workflows/ux-design/steps/step-01b-continue.md +127 -0
  524. package/pennyfarthing-dist/workflows/ux-design/steps/step-02-discovery.md +190 -0
  525. package/pennyfarthing-dist/workflows/ux-design/steps/step-03-core-experience.md +216 -0
  526. package/pennyfarthing-dist/workflows/ux-design/steps/step-04-emotional-response.md +219 -0
  527. package/pennyfarthing-dist/workflows/ux-design/steps/step-05-inspiration.md +234 -0
  528. package/pennyfarthing-dist/workflows/ux-design/steps/step-06-design-system.md +252 -0
  529. package/pennyfarthing-dist/workflows/ux-design/steps/step-07-defining-experience.md +254 -0
  530. package/pennyfarthing-dist/workflows/ux-design/steps/step-08-visual-foundation.md +224 -0
  531. package/pennyfarthing-dist/workflows/ux-design/steps/step-09-design-directions.md +224 -0
  532. package/pennyfarthing-dist/workflows/ux-design/steps/step-10-user-journeys.md +241 -0
  533. package/pennyfarthing-dist/workflows/ux-design/steps/step-11-component-strategy.md +248 -0
  534. package/pennyfarthing-dist/workflows/ux-design/steps/step-12-ux-patterns.md +237 -0
  535. package/pennyfarthing-dist/workflows/ux-design/steps/step-13-responsive-accessibility.md +264 -0
  536. package/pennyfarthing-dist/workflows/ux-design/steps/step-14-complete.md +228 -0
  537. package/pennyfarthing-dist/workflows/ux-design/ux-design-template.md +13 -0
  538. package/pennyfarthing-dist/workflows/ux-design/workflow.yaml +41 -0
@@ -0,0 +1,266 @@
1
+ #!/bin/bash
2
+ # Jira vs YAML Reconciliation Report
3
+ # Usage: .pennyfarthing/scripts/core/run.sh jira/jira-reconcile.sh [--fix]
4
+ #
5
+ # Compares sprint YAML against Jira to find:
6
+ # - Status mismatches
7
+ # - Missing Jira keys
8
+ # - Orphan issues (in Jira but not YAML)
9
+ # - Sprint membership discrepancies
10
+ #
11
+ # Options:
12
+ # --fix Apply recommended fixes automatically (where safe)
13
+
14
+ set -euo pipefail
15
+
16
+ # PROJECT_ROOT should be set by run.sh, but find it if not
17
+ if [[ -z "${PROJECT_ROOT:-}" ]]; then
18
+ d="$PWD"
19
+ while [[ ! -d "$d/.pennyfarthing" ]] && [[ "$d" != "/" ]]; do
20
+ d="$(dirname "$d")"
21
+ done
22
+ PROJECT_ROOT="$d"
23
+ fi
24
+
25
+ SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
26
+ FIX_MODE="${1:-}"
27
+
28
+ # Colors for output
29
+ RED='\033[0;31m'
30
+ GREEN='\033[0;32m'
31
+ YELLOW='\033[1;33m'
32
+ NC='\033[0m' # No Color
33
+
34
+ # Check dependencies
35
+ if ! command -v yq &> /dev/null; then
36
+ echo "Error: yq is required but not installed"
37
+ echo "Install with: brew install yq"
38
+ exit 1
39
+ fi
40
+
41
+ if ! command -v jira &> /dev/null; then
42
+ echo "Error: jira CLI is required but not installed"
43
+ echo "Install with: brew install ankitpokhrel/jira/jira"
44
+ exit 1
45
+ fi
46
+
47
+ if [[ ! -f "$SPRINT_FILE" ]]; then
48
+ echo "Error: Sprint file not found at $SPRINT_FILE"
49
+ exit 1
50
+ fi
51
+
52
+ # Get sprint info
53
+ SPRINT_NAME=$(yq eval '.sprint.name' "$SPRINT_FILE")
54
+ SPRINT_ID=$(yq eval '.sprint.jira_sprint_id' "$SPRINT_FILE")
55
+
56
+ echo "# Jira vs YAML Reconciliation Report"
57
+ echo ""
58
+ echo "**Sprint:** $SPRINT_NAME (Jira Sprint ID: $SPRINT_ID)"
59
+ echo "**Generated:** $(date '+%Y-%m-%d %H:%M')"
60
+ echo ""
61
+
62
+ # Track issues
63
+ STATUS_MISMATCHES=()
64
+ MISSING_JIRA=()
65
+ ORPHAN_ISSUES=()
66
+ NOT_IN_SPRINT=()
67
+
68
+ echo "## Checking YAML Stories Against Jira..."
69
+ echo ""
70
+
71
+ # Extract all stories from YAML and check against Jira
72
+ while IFS=$'\t' read -r yaml_id jira_key yaml_status title; do
73
+ # Skip if no jira key
74
+ if [[ "$jira_key" == "null" ]] || [[ -z "$jira_key" ]]; then
75
+ MISSING_JIRA+=("$yaml_id|$title|$yaml_status")
76
+ continue
77
+ fi
78
+
79
+ # Get Jira status - use sed to remove the key prefix
80
+ jira_status=$(jira issue list --jql "project=MSSCI AND key=$jira_key" --plain --columns key,status --no-headers 2>/dev/null | sed "s/^$jira_key[[:space:]]*//" | xargs || echo "NOT_FOUND")
81
+
82
+ if [[ "$jira_status" == "NOT_FOUND" ]] || [[ -z "$jira_status" ]]; then
83
+ echo -e "${RED}[!]${NC} $jira_key not found in Jira"
84
+ continue
85
+ fi
86
+
87
+ # Normalize statuses for comparison
88
+ jira_norm=$(echo "$jira_status" | tr '[:upper:]' '[:lower:]' | tr ' ' '_')
89
+
90
+ # Check for mismatches
91
+ mismatch=false
92
+ case "$yaml_status" in
93
+ done)
94
+ [[ "$jira_norm" != "done" ]] && mismatch=true
95
+ ;;
96
+ ready|backlog)
97
+ [[ "$jira_norm" != "to_do" ]] && mismatch=true
98
+ ;;
99
+ in_progress)
100
+ [[ "$jira_norm" != "in_progress" ]] && mismatch=true
101
+ ;;
102
+ esac
103
+
104
+ if [[ "$mismatch" == "true" ]]; then
105
+ STATUS_MISMATCHES+=("$jira_key|$yaml_status|$jira_status")
106
+ fi
107
+ done < <(yq -r '.epics[].stories[]? | [.id, .jira, .status, .title] | @tsv' "$SPRINT_FILE" 2>/dev/null)
108
+
109
+ echo ""
110
+ echo "## Checking Jira Sprint Against YAML..."
111
+ echo ""
112
+
113
+ # Get all issues in the Jira sprint and check if they're in YAML
114
+ # Skip canceled issues - they're not relevant
115
+ while read -r jira_key; do
116
+ # Check if in YAML (by id or jira field)
117
+ in_yaml=$(yq -r ".epics[].stories[]? | select(.id == \"$jira_key\" or .jira == \"$jira_key\") | .id" "$SPRINT_FILE" 2>/dev/null | head -1)
118
+
119
+ if [[ -z "$in_yaml" ]]; then
120
+ # Get more info about the orphan
121
+ status=$(jira issue list --jql "project=MSSCI AND key=$jira_key" --plain --columns key,status --no-headers 2>/dev/null | sed "s/^$jira_key[[:space:]]*//" | xargs || echo "Unknown")
122
+
123
+ # Skip canceled issues
124
+ if [[ "$status" == "Canceled" ]]; then
125
+ continue
126
+ fi
127
+
128
+ summary=$(jira issue list --jql "project=MSSCI AND key=$jira_key" --plain --columns key,summary --no-headers 2>/dev/null | sed "s/^$jira_key[[:space:]]*//" | xargs || echo "Unknown")
129
+ ORPHAN_ISSUES+=("$jira_key|$status|$summary")
130
+ fi
131
+ done < <(jira issue list --jql "project=MSSCI AND labels=pennyfarthing AND sprint=$SPRINT_ID AND status != Canceled" --plain --columns key --no-headers 2>/dev/null)
132
+
133
+ echo ""
134
+ echo "## Checking for Issues Not in Sprint..."
135
+ echo ""
136
+
137
+ # Get done issues not in sprint
138
+ while read -r jira_key; do
139
+ # Check if it should be in current sprint (exists in YAML)
140
+ in_yaml=$(yq -r ".epics[].stories[]? | select(.id == \"$jira_key\" or .jira == \"$jira_key\") | .id" "$SPRINT_FILE" 2>/dev/null | head -1)
141
+
142
+ if [[ -n "$in_yaml" ]]; then
143
+ summary=$(jira issue list --jql "project=MSSCI AND key=$jira_key" --plain --columns summary --no-headers 2>/dev/null | xargs || echo "Unknown")
144
+ NOT_IN_SPRINT+=("$jira_key|$summary")
145
+ fi
146
+ done < <(jira issue list --jql "project=MSSCI AND labels=pennyfarthing AND sprint is EMPTY AND status != Canceled" --plain --columns key --no-headers 2>/dev/null)
147
+
148
+ # Output Report
149
+ echo ""
150
+ echo "---"
151
+ echo ""
152
+ echo "# Summary"
153
+ echo ""
154
+
155
+ # Status Mismatches
156
+ echo "## Status Mismatches (${#STATUS_MISMATCHES[@]})"
157
+ echo ""
158
+ if [[ ${#STATUS_MISMATCHES[@]} -eq 0 ]]; then
159
+ echo -e "${GREEN}No status mismatches found.${NC}"
160
+ else
161
+ echo "| Jira Key | YAML Status | Jira Status | Action |"
162
+ echo "|----------|-------------|-------------|--------|"
163
+ for item in "${STATUS_MISMATCHES[@]}"; do
164
+ IFS='|' read -r key yaml jira <<< "$item"
165
+ echo "| $key | $yaml | $jira | Update YAML or Jira |"
166
+ done
167
+ fi
168
+ echo ""
169
+
170
+ # Missing Jira Keys
171
+ echo "## YAML Stories Missing Jira Key (${#MISSING_JIRA[@]})"
172
+ echo ""
173
+ if [[ ${#MISSING_JIRA[@]} -eq 0 ]]; then
174
+ echo -e "${GREEN}All YAML stories have Jira keys.${NC}"
175
+ else
176
+ echo "| YAML ID | Title | Status | Action |"
177
+ echo "|---------|-------|--------|--------|"
178
+ for item in "${MISSING_JIRA[@]}"; do
179
+ IFS='|' read -r id title status <<< "$item"
180
+ echo "| $id | ${title:0:40} | $status | Create Jira issue |"
181
+ done
182
+ fi
183
+ echo ""
184
+
185
+ # Orphan Issues
186
+ echo "## Jira Issues Not in YAML (${#ORPHAN_ISSUES[@]})"
187
+ echo ""
188
+ if [[ ${#ORPHAN_ISSUES[@]} -eq 0 ]]; then
189
+ echo -e "${GREEN}All sprint issues are tracked in YAML.${NC}"
190
+ else
191
+ echo "| Jira Key | Status | Summary | Action |"
192
+ echo "|----------|--------|---------|--------|"
193
+ for item in "${ORPHAN_ISSUES[@]}"; do
194
+ IFS='|' read -r key status summary <<< "$item"
195
+ if [[ "$status" == "Done" ]]; then
196
+ echo "| $key | $status | ${summary:0:40} | Info: Completed (not in current YAML) |"
197
+ else
198
+ echo "| $key | $status | ${summary:0:40} | Add to YAML or remove from sprint |"
199
+ fi
200
+ done
201
+ echo ""
202
+ echo "*Note: Done issues not in YAML are historical - they count toward sprint velocity but aren't actively tracked.*"
203
+ fi
204
+ echo ""
205
+
206
+ # Not in Sprint
207
+ echo "## YAML Stories Not in Jira Sprint (${#NOT_IN_SPRINT[@]})"
208
+ echo ""
209
+ if [[ ${#NOT_IN_SPRINT[@]} -eq 0 ]]; then
210
+ echo -e "${GREEN}All YAML stories are in Jira sprint.${NC}"
211
+ else
212
+ echo "| Jira Key | Summary | Action |"
213
+ echo "|----------|---------|--------|"
214
+ for item in "${NOT_IN_SPRINT[@]}"; do
215
+ IFS='|' read -r key summary <<< "$item"
216
+ echo "| $key | ${summary:0:50} | Add to sprint $SPRINT_ID |"
217
+ done
218
+ fi
219
+ echo ""
220
+
221
+ # Epic check
222
+ echo "## Epic Sync Check"
223
+ echo ""
224
+ echo "| YAML Epic ID | Jira Field | Status |"
225
+ echo "|--------------|------------|--------|"
226
+ while IFS=$'\t' read -r epic_id jira_key title; do
227
+ if [[ "$jira_key" == "null" ]] || [[ -z "$jira_key" ]]; then
228
+ echo -e "| $epic_id | ${RED}MISSING${NC} | $title |"
229
+ else
230
+ echo "| $epic_id | $jira_key | $title |"
231
+ fi
232
+ done < <(yq -r '.epics[] | [.id, .jira, .title] | @tsv' "$SPRINT_FILE" 2>/dev/null)
233
+ echo ""
234
+
235
+ # Total counts
236
+ total_issues=$((${#STATUS_MISMATCHES[@]} + ${#MISSING_JIRA[@]} + ${#ORPHAN_ISSUES[@]} + ${#NOT_IN_SPRINT[@]}))
237
+
238
+ echo "---"
239
+ echo ""
240
+ if [[ $total_issues -eq 0 ]]; then
241
+ echo -e "${GREEN}Sync Status: CLEAN${NC} - No discrepancies found!"
242
+ else
243
+ echo -e "${YELLOW}Sync Status: $total_issues issue(s) found${NC}"
244
+ echo ""
245
+ echo "Run with --fix to apply automatic fixes where possible."
246
+ fi
247
+
248
+ # Fix mode
249
+ if [[ "$FIX_MODE" == "--fix" ]]; then
250
+ echo ""
251
+ echo "## Applying Fixes..."
252
+ echo ""
253
+
254
+ # Add stories to sprint
255
+ for item in "${NOT_IN_SPRINT[@]}"; do
256
+ IFS='|' read -r key summary <<< "$item"
257
+ echo "Adding $key to sprint $SPRINT_ID..."
258
+ jira sprint add "$SPRINT_ID" "$key" 2>/dev/null && echo " Done" || echo " Failed"
259
+ done
260
+
261
+ echo ""
262
+ echo "Fix mode completed. Manual review still needed for:"
263
+ echo "- Status mismatches (requires decision on which source is correct)"
264
+ echo "- Missing Jira keys (requires creating new issues)"
265
+ echo "- Orphan issues (requires adding to YAML or removing from sprint)"
266
+ fi
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env zsh
2
+ # Sync a single story between sprint YAML and Jira
3
+ # Usage: jira-sync-story.sh <story_key> [--transition] [--points] [--comment "message"]
4
+ #
5
+ # Thin wrapper that delegates to Python CLI:
6
+ # python -m pennyfarthing_scripts.jira create story <story_key> [options]
7
+ #
8
+ # Note: The subcommand is 'create story' but it handles sync, not creation.
9
+
10
+ set -e
11
+
12
+ # Source common functions for Python discovery
13
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
14
+ PARENT_DIR="$(dirname "$SCRIPT_DIR")"
15
+ source "${PARENT_DIR}/lib/common.sh"
16
+
17
+ # Delegate to Python CLI
18
+ run_python_module jira create story "$@"
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env zsh
2
+ # Sync an epic and its stories to Jira
3
+ # Usage: jira-sync.sh <epic_number> [--dry-run] [--transition] [--points]
4
+ #
5
+ # Thin wrapper that delegates to Python CLI:
6
+ # python -m pennyfarthing_scripts.jira sync <epic_number> [options]
7
+
8
+ set -e
9
+
10
+ # Source common functions for Python discovery
11
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
12
+ PARENT_DIR="$(dirname "$SCRIPT_DIR")"
13
+ source "${PARENT_DIR}/lib/common.sh"
14
+
15
+ # Delegate to Python CLI
16
+ run_python_module jira sync "$@"
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env zsh
2
+ # Sync an epic and its stories to Jira
3
+ # Usage: sync-epic-jira.sh <epic-id> [--dry-run] [--transition] [--points] [--all]
4
+ #
5
+ # Thin wrapper that delegates to Python CLI:
6
+ # python -m pennyfarthing_scripts.jira sync <epic-id> [options]
7
+
8
+ set -e
9
+
10
+ # Source common functions for Python discovery
11
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
12
+ PARENT_DIR="$(dirname "$SCRIPT_DIR")"
13
+ source "${PARENT_DIR}/lib/common.sh"
14
+
15
+ # Delegate to Python CLI
16
+ run_python_module jira sync "$@"
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env zsh
2
+ # Sync Pennyfarthing Epic to Jira MSSCI Project using jira
3
+ # Usage: ./scripts/sync-epic-to-jira.sh <epic_number> [--dry-run] [--with-comments]
4
+ #
5
+ # Prerequisites:
6
+ # - jira installed: brew install ankitpokhrel/jira/jira
7
+ # - jira configured: jira init
8
+ # - JIRA_API_TOKEN environment variable set
9
+ #
10
+ # Options:
11
+ # --dry-run Show what would be done without making changes
12
+ # --with-comments (Deprecated - kept for compatibility)
13
+
14
+ # Delegate to jira-sync.sh which implements the actual sync logic
15
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
16
+ exec "${SCRIPT_DIR}/jira-sync.sh" "$@"
@@ -0,0 +1,29 @@
1
+ # Library Scripts
2
+
3
+ Shared bash libraries sourced by other scripts.
4
+
5
+ ## Libraries
6
+
7
+ | Script | Purpose |
8
+ |--------|---------|
9
+ | `common.sh` | Common utilities (colors, logging basics) |
10
+ | `logging.sh` | Structured logging functions |
11
+ | `retry.sh` | Retry logic with exponential backoff |
12
+ | `checkpoint.sh` | Checkpointing for long-running operations |
13
+ | `file-lock.sh` | File locking utilities |
14
+ | `background-tasks.sh` | Background task management |
15
+ | `find-root.sh` | Project root finder |
16
+
17
+ ## Usage
18
+
19
+ These are sourced by other scripts, not run directly:
20
+
21
+ ```bash
22
+ source "$SCRIPTS_DIR/lib/common.sh"
23
+ source "$SCRIPTS_DIR/lib/logging.sh"
24
+ ```
25
+
26
+ ## Ownership
27
+
28
+ - **Primary users:** All scripts
29
+ - **Maintained by:** Core Pennyfarthing team
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env bash
2
+ # Background task tracking utilities for session files
3
+ #
4
+ # Usage:
5
+ # source $CLAUDE_PROJECT_DIR/scripts/lib/background-tasks.sh
6
+ #
7
+ # Functions:
8
+ # bg_task_add <session_file> <task_id> <subagent_type> <description>
9
+ # bg_task_update <session_file> <task_id> <status>
10
+ # bg_task_cleanup <session_file>
11
+ # bg_task_list <session_file>
12
+ # bg_task_check <session_file>
13
+ #
14
+ # Example:
15
+ # # After spawning background task
16
+ # bg_task_add "$SESSION_FILE" "abc123" "testing-runner" "Background test run"
17
+ #
18
+ # # After TaskOutput returns
19
+ # bg_task_update "$SESSION_FILE" "abc123" "completed"
20
+ # bg_task_cleanup "$SESSION_FILE"
21
+
22
+ set -euo pipefail
23
+
24
+ # Helper: count pattern matches in file (returns 0 if no matches)
25
+ # grep -c outputs "0" AND exits 1 when no matches, so we capture and fallback separately
26
+ _count_matches() {
27
+ local count
28
+ count=$(grep -c "$1" "$2" 2>/dev/null) || count=0
29
+ echo "$count"
30
+ }
31
+
32
+ # Add a background task to session file
33
+ # Creates the Background Tasks section if it doesn't exist
34
+ bg_task_add() {
35
+ local session_file="$1"
36
+ local task_id="$2"
37
+ local subagent_type="$3"
38
+ local description="${4:-}"
39
+ local timestamp
40
+ timestamp=$(date +"%H:%M")
41
+
42
+ if [[ ! -f "$session_file" ]]; then
43
+ echo "ERROR: Session file not found: $session_file" >&2
44
+ return 1
45
+ fi
46
+
47
+ # Check if Background Tasks section exists
48
+ if ! grep -q "^## Background Tasks" "$session_file" 2>/dev/null; then
49
+ # Add section before Workflow Tracking if present, otherwise at end
50
+ if grep -q "^## Workflow Tracking" "$session_file"; then
51
+ # Insert before Workflow Tracking using awk
52
+ awk '/^## Workflow Tracking/ {
53
+ print "## Background Tasks\n"
54
+ print "| Task ID | Type | Started | Status | Description |"
55
+ print "|---------|------|---------|--------|-------------|"
56
+ print ""
57
+ } {print}' "$session_file" > "${session_file}.tmp" && mv "${session_file}.tmp" "$session_file"
58
+ else
59
+ # Append to end
60
+ cat >> "$session_file" << EOF
61
+
62
+ ## Background Tasks
63
+
64
+ | Task ID | Type | Started | Status | Description |
65
+ |---------|------|---------|--------|-------------|
66
+ EOF
67
+ fi
68
+ fi
69
+
70
+ # Add task row after the table header
71
+ awk -v tid="$task_id" -v stype="$subagent_type" -v ts="$timestamp" -v desc="$description" '
72
+ /^\|[-]+\|/ && in_section {
73
+ print
74
+ print "| " tid " | " stype " | " ts " | running | " desc " |"
75
+ next
76
+ }
77
+ /^## Background Tasks/ { in_section=1 }
78
+ /^## / && !/^## Background Tasks/ { in_section=0 }
79
+ { print }
80
+ ' "$session_file" > "${session_file}.tmp" && mv "${session_file}.tmp" "$session_file"
81
+
82
+ echo "Added background task: $task_id ($subagent_type)"
83
+ }
84
+
85
+ # Update background task status
86
+ # Status: running, completed, error
87
+ bg_task_update() {
88
+ local session_file="$1"
89
+ local task_id="$2"
90
+ local new_status="$3"
91
+
92
+ if [[ ! -f "$session_file" ]]; then
93
+ echo "ERROR: Session file not found: $session_file" >&2
94
+ return 1
95
+ fi
96
+
97
+ if ! grep -q "| $task_id |" "$session_file" 2>/dev/null; then
98
+ echo "WARNING: Task $task_id not found in session file" >&2
99
+ return 0
100
+ fi
101
+
102
+ # Update the status column for this task
103
+ sed -i '' "s/| $task_id |\\([^|]*\\)|\\([^|]*\\)| running |/| $task_id |\\1|\\2| $new_status |/" "$session_file"
104
+ echo "Updated task $task_id: $new_status"
105
+ }
106
+
107
+ # Remove completed and error tasks from session file
108
+ bg_task_cleanup() {
109
+ local session_file="$1"
110
+
111
+ if [[ ! -f "$session_file" ]]; then
112
+ echo "ERROR: Session file not found: $session_file" >&2
113
+ return 1
114
+ fi
115
+
116
+ # Count tasks to remove
117
+ local completed_count
118
+ completed_count=$(_count_matches "| completed |" "$session_file")
119
+ local error_count
120
+ error_count=$(_count_matches "| error |" "$session_file")
121
+
122
+ if [[ "$completed_count" -gt 0 ]] || [[ "$error_count" -gt 0 ]]; then
123
+ sed -i '' '/| completed |/d' "$session_file"
124
+ sed -i '' '/| error |/d' "$session_file"
125
+ echo "Cleaned up $completed_count completed, $error_count errored tasks"
126
+ fi
127
+ }
128
+
129
+ # List active (running) background tasks
130
+ bg_task_list() {
131
+ local session_file="$1"
132
+
133
+ if [[ ! -f "$session_file" ]]; then
134
+ echo "No session file"
135
+ return 0
136
+ fi
137
+
138
+ local running_tasks
139
+ running_tasks=$(grep "| running |" "$session_file" 2>/dev/null || true)
140
+
141
+ if [[ -n "$running_tasks" ]]; then
142
+ echo "$running_tasks"
143
+ else
144
+ echo "No active background tasks"
145
+ fi
146
+ }
147
+
148
+ # Check for active background tasks (returns 0 if tasks exist, 1 if none)
149
+ # Useful for conditional logic in scripts
150
+ bg_task_check() {
151
+ local session_file="$1"
152
+
153
+ if [[ ! -f "$session_file" ]]; then
154
+ return 1
155
+ fi
156
+
157
+ grep -q "| running |" "$session_file" 2>/dev/null
158
+ }
159
+
160
+ # Print summary of all background tasks
161
+ bg_task_summary() {
162
+ local session_file="$1"
163
+
164
+ if [[ ! -f "$session_file" ]]; then
165
+ echo "No session file"
166
+ return 0
167
+ fi
168
+
169
+ local running
170
+ running=$(_count_matches "| running |" "$session_file")
171
+ local completed
172
+ completed=$(_count_matches "| completed |" "$session_file")
173
+ local errored
174
+ errored=$(_count_matches "| error |" "$session_file")
175
+
176
+ echo "Background tasks: $running running, $completed completed, $errored errored"
177
+ }
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env zsh
2
+ # Session checkpointing utilities
3
+ # Dev: Fanny Price - "I was quiet, but I was not blind."
4
+
5
+ # Source file locking utilities
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ # shellcheck source=file-lock.sh
8
+ source "${SCRIPT_DIR}/file-lock.sh" 2>/dev/null || true
9
+
10
+ # Checkpoint file location (evaluated dynamically)
11
+ _get_checkpoint_file() {
12
+ echo "${PROJECT_ROOT:-.}/.session/checkpoints.log"
13
+ }
14
+
15
+ # checkpoint_save LABEL DATA
16
+ # Save a checkpoint with timestamp
17
+ #
18
+ # Arguments:
19
+ # LABEL - Identifier for this checkpoint
20
+ # DATA - Data to save (string)
21
+ #
22
+ # Format: ISO_TIMESTAMP|LABEL|DATA
23
+ #
24
+ # Example:
25
+ # checkpoint_save "story_phase" "dev"
26
+ # checkpoint_save "last_file" "src/main.go:42"
27
+ #
28
+ checkpoint_save() {
29
+ local label="$1"
30
+ local data="$2"
31
+ local timestamp
32
+ local checkpoint_file
33
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
34
+ checkpoint_file=$(_get_checkpoint_file)
35
+
36
+ # Ensure directory exists
37
+ mkdir -p "$(dirname "$checkpoint_file")"
38
+
39
+ # Acquire exclusive lock, append checkpoint, release lock
40
+ if lock_acquire "$checkpoint_file" "exclusive" 5 2>/dev/null; then
41
+ echo "${timestamp}|${label}|${data}" >> "$checkpoint_file"
42
+ lock_release "$checkpoint_file"
43
+ else
44
+ # Fallback: append without lock (better than failing)
45
+ echo "${timestamp}|${label}|${data}" >> "$checkpoint_file"
46
+ fi
47
+ }
48
+
49
+ # checkpoint_restore LABEL
50
+ # Restore the most recent checkpoint with given label
51
+ #
52
+ # Arguments:
53
+ # LABEL - Identifier to look up
54
+ #
55
+ # Returns:
56
+ # Outputs the data portion of the most recent matching checkpoint
57
+ # Empty if no match found
58
+ #
59
+ # Example:
60
+ # phase=$(checkpoint_restore "story_phase")
61
+ #
62
+ checkpoint_restore() {
63
+ local label="$1"
64
+ local checkpoint_file
65
+ checkpoint_file=$(_get_checkpoint_file)
66
+
67
+ if [[ ! -f "$checkpoint_file" ]]; then
68
+ return 0
69
+ fi
70
+
71
+ # Find entries with matching label, take the last one, extract data field
72
+ # Use || true to handle case where grep finds no matches
73
+ grep "|${label}|" "$checkpoint_file" 2>/dev/null | tail -1 | cut -d'|' -f3- || true
74
+ }
75
+
76
+ # checkpoint_list
77
+ # List recent checkpoints (last 20)
78
+ #
79
+ # Example:
80
+ # checkpoint_list
81
+ #
82
+ checkpoint_list() {
83
+ local checkpoint_file
84
+ checkpoint_file=$(_get_checkpoint_file)
85
+
86
+ if [[ -f "$checkpoint_file" ]]; then
87
+ tail -20 "$checkpoint_file"
88
+ fi
89
+ }
90
+
91
+ # checkpoint_clear
92
+ # Remove all checkpoints
93
+ #
94
+ # Example:
95
+ # checkpoint_clear
96
+ #
97
+ checkpoint_clear() {
98
+ local checkpoint_file
99
+ checkpoint_file=$(_get_checkpoint_file)
100
+ rm -f "$checkpoint_file"
101
+ }
102
+
103
+ # checkpoint_rotate MAX_LINES
104
+ # Rotate checkpoint file to prevent unbounded growth
105
+ #
106
+ # Arguments:
107
+ # MAX_LINES - Maximum lines to keep (default: 1000)
108
+ #
109
+ # Example:
110
+ # checkpoint_rotate 500
111
+ #
112
+ checkpoint_rotate() {
113
+ local max_lines=${1:-1000}
114
+ local checkpoint_file
115
+ checkpoint_file=$(_get_checkpoint_file)
116
+
117
+ if [[ ! -f "$checkpoint_file" ]]; then
118
+ return 0
119
+ fi
120
+
121
+ # Acquire exclusive lock for rotation
122
+ if lock_acquire "$checkpoint_file" "exclusive" 5 2>/dev/null; then
123
+ local current_lines
124
+ current_lines=$(wc -l < "$checkpoint_file")
125
+
126
+ if ((current_lines > max_lines)); then
127
+ local temp_file
128
+ temp_file=$(mktemp)
129
+ tail -n "$max_lines" "$checkpoint_file" > "$temp_file"
130
+ mv "$temp_file" "$checkpoint_file"
131
+ fi
132
+ lock_release "$checkpoint_file"
133
+ fi
134
+ }
135
+
136
+ # Functions available when sourced