@pennyfarthing/core 10.0.5 → 10.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (580) hide show
  1. package/README.md +19 -22
  2. package/package.json +17 -11
  3. package/packages/core/dist/cli/commands/doctor-file-layout.test.js.map +1 -1
  4. package/packages/core/dist/cli/commands/doctor-legacy.test.js +24 -0
  5. package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
  6. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  7. package/packages/core/dist/cli/commands/doctor.js +346 -13
  8. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  9. package/packages/core/dist/cli/commands/e2e-fresh-install.test.js +1 -1
  10. package/packages/core/dist/cli/commands/e2e-fresh-install.test.js.map +1 -1
  11. package/packages/core/dist/cli/commands/e2e-upgrade.test.js +1 -1
  12. package/packages/core/dist/cli/commands/e2e-upgrade.test.js.map +1 -1
  13. package/packages/core/dist/cli/commands/hooks-consolidation.test.js +2 -2
  14. package/packages/core/dist/cli/commands/hooks-consolidation.test.js.map +1 -1
  15. package/packages/core/dist/cli/commands/init-consolidation.test.js.map +1 -1
  16. package/packages/core/dist/cli/commands/init.d.ts +7 -0
  17. package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
  18. package/packages/core/dist/cli/commands/init.js +41 -8
  19. package/packages/core/dist/cli/commands/init.js.map +1 -1
  20. package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -1
  21. package/packages/core/dist/cli/commands/uninstall.js +24 -13
  22. package/packages/core/dist/cli/commands/uninstall.js.map +1 -1
  23. package/packages/core/dist/cli/commands/update-consolidation.test.js +0 -10
  24. package/packages/core/dist/cli/commands/update-consolidation.test.js.map +1 -1
  25. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  26. package/packages/core/dist/cli/commands/update.js +26 -0
  27. package/packages/core/dist/cli/commands/update.js.map +1 -1
  28. package/packages/core/dist/cli/index.js +1 -1
  29. package/packages/core/dist/cli/index.js.map +1 -1
  30. package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
  31. package/packages/core/dist/cli/theme-maker.test.js +64 -115
  32. package/packages/core/dist/cli/theme-maker.test.js.map +1 -1
  33. package/packages/core/dist/cli/utils/python.d.ts +22 -0
  34. package/packages/core/dist/cli/utils/python.d.ts.map +1 -0
  35. package/packages/core/dist/cli/utils/python.js +102 -0
  36. package/packages/core/dist/cli/utils/python.js.map +1 -0
  37. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  38. package/packages/core/dist/cli/utils/settings.js +10 -0
  39. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  40. package/packages/core/dist/index.d.ts +1 -1
  41. package/packages/core/dist/index.d.ts.map +1 -1
  42. package/packages/core/dist/index.js +2 -2
  43. package/packages/core/dist/index.js.map +1 -1
  44. package/packages/core/dist/plugins/plugin-discovery.d.ts +116 -0
  45. package/packages/core/dist/plugins/plugin-discovery.d.ts.map +1 -0
  46. package/packages/core/dist/plugins/plugin-discovery.js +165 -0
  47. package/packages/core/dist/plugins/plugin-discovery.js.map +1 -0
  48. package/packages/core/dist/plugins/plugin-discovery.test.d.ts +22 -0
  49. package/packages/core/dist/plugins/plugin-discovery.test.d.ts.map +1 -0
  50. package/packages/core/dist/plugins/plugin-discovery.test.js +498 -0
  51. package/packages/core/dist/plugins/plugin-discovery.test.js.map +1 -0
  52. package/packages/core/dist/scripts/generate-spider-report.js.map +1 -1
  53. package/packages/core/dist/workflow/context-watch.d.ts +80 -0
  54. package/packages/core/dist/workflow/context-watch.d.ts.map +1 -0
  55. package/packages/core/dist/workflow/context-watch.js +235 -0
  56. package/packages/core/dist/workflow/context-watch.js.map +1 -0
  57. package/packages/core/dist/workflow/context-watch.test.d.ts +1 -0
  58. package/packages/core/dist/workflow/context-watch.test.d.ts.map +1 -0
  59. package/packages/core/dist/workflow/context-watch.test.js +746 -0
  60. package/packages/core/dist/workflow/context-watch.test.js.map +1 -0
  61. package/packages/core/dist/workflow/file-watch.d.ts +82 -0
  62. package/packages/core/dist/workflow/file-watch.d.ts.map +1 -0
  63. package/packages/core/dist/workflow/file-watch.js +198 -0
  64. package/packages/core/dist/workflow/file-watch.js.map +1 -0
  65. package/packages/core/dist/workflow/file-watch.test.d.ts +21 -0
  66. package/packages/core/dist/workflow/file-watch.test.d.ts.map +1 -0
  67. package/packages/core/dist/workflow/file-watch.test.js +469 -0
  68. package/packages/core/dist/workflow/file-watch.test.js.map +1 -0
  69. package/packages/core/dist/workflow/observation-writer.d.ts +79 -0
  70. package/packages/core/dist/workflow/observation-writer.d.ts.map +1 -0
  71. package/packages/core/dist/workflow/observation-writer.js +97 -0
  72. package/packages/core/dist/workflow/observation-writer.js.map +1 -0
  73. package/packages/core/dist/workflow/observation-writer.test.d.ts +18 -0
  74. package/packages/core/dist/workflow/observation-writer.test.d.ts.map +1 -0
  75. package/packages/core/dist/workflow/observation-writer.test.js +424 -0
  76. package/packages/core/dist/workflow/observation-writer.test.js.map +1 -0
  77. package/packages/core/dist/workflow/story-workflow-routing.test.js +4 -2
  78. package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -1
  79. package/packages/core/dist/workflow/tandem-lifecycle.d.ts +117 -0
  80. package/packages/core/dist/workflow/tandem-lifecycle.d.ts.map +1 -0
  81. package/packages/core/dist/workflow/tandem-lifecycle.js +186 -0
  82. package/packages/core/dist/workflow/tandem-lifecycle.js.map +1 -0
  83. package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts +16 -0
  84. package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts.map +1 -0
  85. package/packages/core/dist/workflow/tandem-lifecycle.test.js +531 -0
  86. package/packages/core/dist/workflow/tandem-lifecycle.test.js.map +1 -0
  87. package/packages/core/dist/workflow/tool-watch.d.ts +68 -0
  88. package/packages/core/dist/workflow/tool-watch.d.ts.map +1 -0
  89. package/packages/core/dist/workflow/tool-watch.js +166 -0
  90. package/packages/core/dist/workflow/tool-watch.js.map +1 -0
  91. package/packages/core/dist/workflow/tool-watch.test.d.ts +18 -0
  92. package/packages/core/dist/workflow/tool-watch.test.d.ts.map +1 -0
  93. package/packages/core/dist/workflow/tool-watch.test.js +718 -0
  94. package/packages/core/dist/workflow/tool-watch.test.js.map +1 -0
  95. package/packages/core/dist/workflow/workflow-migration.test.js +8 -4
  96. package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -1
  97. package/packages/core/dist/workflow/workflow-schema.d.ts +7 -0
  98. package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
  99. package/packages/core/dist/workflow/workflow-schema.js +44 -0
  100. package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
  101. package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
  102. package/packages/core/dist/workflow/workflow-schema.test.js +192 -0
  103. package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
  104. package/pennyfarthing-dist/agents/README.md +1 -3
  105. package/pennyfarthing-dist/agents/architect.md +0 -6
  106. package/pennyfarthing-dist/agents/devops.md +0 -6
  107. package/pennyfarthing-dist/agents/handoff.md +18 -3
  108. package/pennyfarthing-dist/agents/orchestrator.md +0 -6
  109. package/pennyfarthing-dist/agents/pm.md +0 -6
  110. package/pennyfarthing-dist/agents/sm-finish.md +1 -1
  111. package/pennyfarthing-dist/agents/sm-handoff.md +27 -4
  112. package/pennyfarthing-dist/agents/sm.md +11 -11
  113. package/pennyfarthing-dist/agents/tandem-backseat.md +119 -0
  114. package/pennyfarthing-dist/commands/architect.md +11 -3
  115. package/pennyfarthing-dist/commands/close-epic.md +24 -131
  116. package/pennyfarthing-dist/commands/create-theme.md +14 -24
  117. package/pennyfarthing-dist/commands/dev.md +11 -3
  118. package/pennyfarthing-dist/commands/devops.md +11 -3
  119. package/pennyfarthing-dist/commands/health-check.md +1 -3
  120. package/pennyfarthing-dist/commands/help.md +8 -12
  121. package/pennyfarthing-dist/commands/list-themes.md +14 -16
  122. package/pennyfarthing-dist/commands/orchestrator.md +11 -3
  123. package/pennyfarthing-dist/commands/parallel-work.md +1 -3
  124. package/pennyfarthing-dist/commands/pm.md +11 -3
  125. package/pennyfarthing-dist/commands/prime.md +6 -6
  126. package/pennyfarthing-dist/commands/reviewer.md +11 -3
  127. package/pennyfarthing-dist/commands/run-ci.md +1 -1
  128. package/pennyfarthing-dist/commands/set-theme.md +14 -51
  129. package/pennyfarthing-dist/commands/setup.md +5 -1
  130. package/pennyfarthing-dist/commands/show-theme.md +14 -16
  131. package/pennyfarthing-dist/commands/sm.md +11 -3
  132. package/pennyfarthing-dist/commands/tea.md +11 -3
  133. package/pennyfarthing-dist/commands/tech-writer.md +11 -3
  134. package/pennyfarthing-dist/commands/theme-maker.md +14 -671
  135. package/pennyfarthing-dist/commands/theme.md +95 -0
  136. package/pennyfarthing-dist/commands/ux-designer.md +11 -3
  137. package/pennyfarthing-dist/commands/work.md +3 -5
  138. package/pennyfarthing-dist/guides/agent-behavior.md +62 -6
  139. package/pennyfarthing-dist/guides/agent-coordination.md +11 -13
  140. package/pennyfarthing-dist/guides/agent-template-tactical.md +2 -3
  141. package/pennyfarthing-dist/guides/bikelane.md +3 -2
  142. package/pennyfarthing-dist/guides/command-tag-taxonomy.md +212 -0
  143. package/pennyfarthing-dist/guides/hooks.md +5 -5
  144. package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +3 -3
  145. package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +9 -59
  146. package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +4 -5
  147. package/pennyfarthing-dist/guides/prime.md +2 -2
  148. package/pennyfarthing-dist/guides/scale-levels.md +4 -6
  149. package/pennyfarthing-dist/guides/skill-schema.md +4 -4
  150. package/pennyfarthing-dist/guides/tandem-protocol.md +158 -0
  151. package/pennyfarthing-dist/personas/themes/discworld.yaml +1 -1
  152. package/pennyfarthing-dist/personas/themes/fifth-element.yaml +295 -0
  153. package/pennyfarthing-dist/scripts/README.md +1 -1
  154. package/pennyfarthing-dist/scripts/core/agent-session.sh +6 -2
  155. package/pennyfarthing-dist/scripts/core/check-context.sh +0 -0
  156. package/pennyfarthing-dist/scripts/core/handoff-marker.sh +0 -0
  157. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +0 -0
  158. package/pennyfarthing-dist/scripts/core/prime.sh +8 -10
  159. package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +0 -0
  160. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +0 -0
  161. package/pennyfarthing-dist/scripts/git/git-status-all.sh +0 -0
  162. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +8 -6
  163. package/pennyfarthing-dist/scripts/git/release.sh +0 -0
  164. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +0 -0
  165. package/pennyfarthing-dist/scripts/health/drift-detection.sh +0 -0
  166. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +131 -54
  167. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +0 -0
  168. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +0 -0
  169. package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +0 -0
  170. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +0 -0
  171. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +32 -15
  172. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +4 -3
  173. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +0 -0
  174. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +11 -5
  175. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +0 -0
  176. package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +0 -0
  177. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +0 -0
  178. package/pennyfarthing-dist/scripts/hooks/session-start.sh +0 -0
  179. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +0 -0
  180. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +0 -0
  181. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +0 -0
  182. package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +0 -0
  183. package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +0 -0
  184. package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +0 -0
  185. package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +0 -0
  186. package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +0 -0
  187. package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +0 -0
  188. package/pennyfarthing-dist/scripts/lib/background-tasks.sh +0 -0
  189. package/pennyfarthing-dist/scripts/lib/checkpoint.sh +0 -0
  190. package/pennyfarthing-dist/scripts/lib/common.sh +0 -0
  191. package/pennyfarthing-dist/scripts/lib/file-lock.sh +0 -0
  192. package/pennyfarthing-dist/scripts/lib/logging.sh +0 -0
  193. package/pennyfarthing-dist/scripts/lib/retry.sh +0 -0
  194. package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +0 -0
  195. package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +0 -0
  196. package/pennyfarthing-dist/scripts/misc/README.md +1 -1
  197. package/pennyfarthing-dist/scripts/misc/add-short-names.sh +0 -0
  198. package/pennyfarthing-dist/scripts/misc/add_short_names.py +0 -0
  199. package/pennyfarthing-dist/scripts/misc/backlog.sh +0 -0
  200. package/pennyfarthing-dist/scripts/misc/check-status.sh +0 -0
  201. package/pennyfarthing-dist/scripts/misc/find-related-work.sh +0 -0
  202. package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +0 -0
  203. package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +0 -0
  204. package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +0 -0
  205. package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +0 -0
  206. package/pennyfarthing-dist/scripts/misc/repo-scan.sh +0 -0
  207. package/pennyfarthing-dist/scripts/misc/repo-utils.sh +0 -0
  208. package/pennyfarthing-dist/scripts/misc/run-ci.sh +0 -0
  209. package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +0 -0
  210. package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +0 -0
  211. package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +0 -0
  212. package/pennyfarthing-dist/scripts/misc/statusline.sh +50 -8
  213. package/pennyfarthing-dist/scripts/misc/uninstall.sh +0 -0
  214. package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +1 -2
  215. package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +0 -0
  216. package/pennyfarthing-dist/scripts/story/create-story.sh +0 -0
  217. package/pennyfarthing-dist/scripts/story/size-story.sh +0 -0
  218. package/pennyfarthing-dist/scripts/story/story-template.sh +0 -0
  219. package/pennyfarthing-dist/scripts/tests/check.test.sh +0 -0
  220. package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +0 -0
  221. package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +0 -0
  222. package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +5 -5
  223. package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +0 -0
  224. package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +0 -0
  225. package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +0 -0
  226. package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +0 -0
  227. package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +0 -0
  228. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +3 -79
  229. package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +0 -0
  230. package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +0 -0
  231. package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +0 -0
  232. package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +0 -0
  233. package/pennyfarthing-dist/scripts/theme/README.md +1 -1
  234. package/pennyfarthing-dist/scripts/theme/list-themes.sh +0 -0
  235. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +0 -1
  236. package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
  237. package/pennyfarthing-dist/scripts/workflow/check.py +0 -0
  238. package/pennyfarthing-dist/scripts/workflow/check.sh +0 -0
  239. package/pennyfarthing-dist/scripts/workflow/complete-step.py +0 -0
  240. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +10 -144
  241. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +0 -0
  242. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +0 -0
  243. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +0 -0
  244. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +0 -0
  245. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +0 -0
  246. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +0 -0
  247. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +0 -0
  248. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +0 -0
  249. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +0 -0
  250. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +2 -2
  251. package/pennyfarthing-dist/skills/skill-registry.schema.json +8 -0
  252. package/pennyfarthing-dist/skills/skill-registry.yaml +21 -17
  253. package/pennyfarthing-dist/skills/sprint/skill.md +25 -2
  254. package/pennyfarthing-dist/skills/story/scripts/create-story.sh +0 -0
  255. package/pennyfarthing-dist/skills/story/scripts/size-story.sh +0 -0
  256. package/pennyfarthing-dist/skills/story/scripts/story-template.sh +0 -0
  257. package/pennyfarthing-dist/skills/theme/skill.md +290 -75
  258. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +23 -166
  259. package/pennyfarthing-dist/skills/workflow/scripts/list-workflows.sh +0 -0
  260. package/pennyfarthing-dist/skills/workflow/scripts/resume-workflow.sh +0 -0
  261. package/pennyfarthing-dist/skills/workflow/scripts/show-workflow.sh +0 -0
  262. package/pennyfarthing-dist/skills/workflow/scripts/start-workflow.sh +0 -0
  263. package/pennyfarthing-dist/skills/workflow/scripts/workflow-status.sh +0 -0
  264. package/pennyfarthing-dist/skills/workflow/skill.md +27 -4
  265. package/pennyfarthing-dist/templates/agent-scopes.yaml.template +0 -11
  266. package/pennyfarthing-dist/templates/auto-load-sm.sh.template +14 -0
  267. package/pennyfarthing-dist/templates/settings.local.json.template +9 -0
  268. package/pennyfarthing-dist/workflows/2party-tdd.yaml +399 -0
  269. package/pennyfarthing-dist/workflows/architecture/workflow.yaml +65 -0
  270. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +70 -0
  271. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +41 -24
  272. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +61 -0
  273. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  276. package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
  277. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  278. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  279. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  280. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  281. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  282. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  283. package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
  284. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  285. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  286. package/pennyfarthing_scripts/bellmode_hook.py +202 -47
  287. package/pennyfarthing_scripts/brownfield/__init__.py +6 -6
  288. package/pennyfarthing_scripts/brownfield/__main__.py +1 -0
  289. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  290. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  291. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  292. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  293. package/pennyfarthing_scripts/brownfield/cli.py +0 -1
  294. package/pennyfarthing_scripts/brownfield/discover.py +1 -2
  295. package/pennyfarthing_scripts/cli.py +23 -3
  296. package/pennyfarthing_scripts/codemarkers/__init__.py +23 -0
  297. package/pennyfarthing_scripts/codemarkers/__main__.py +6 -0
  298. package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
  299. package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
  300. package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
  301. package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
  302. package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
  303. package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
  304. package/pennyfarthing_scripts/codemarkers/analyze.py +501 -0
  305. package/pennyfarthing_scripts/codemarkers/cli.py +179 -0
  306. package/pennyfarthing_scripts/codemarkers/formatters.py +88 -0
  307. package/pennyfarthing_scripts/codemarkers/models.py +60 -0
  308. package/pennyfarthing_scripts/common/__init__.py +8 -9
  309. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  310. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  311. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  312. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  313. package/pennyfarthing_scripts/common/config.py +1 -1
  314. package/pennyfarthing_scripts/complexity/__init__.py +15 -0
  315. package/pennyfarthing_scripts/complexity/__main__.py +6 -0
  316. package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
  317. package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
  318. package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
  319. package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
  320. package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
  321. package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
  322. package/pennyfarthing_scripts/complexity/analyze.py +207 -0
  323. package/pennyfarthing_scripts/complexity/cli.py +82 -0
  324. package/pennyfarthing_scripts/complexity/formatters.py +64 -0
  325. package/pennyfarthing_scripts/complexity/models.py +32 -0
  326. package/pennyfarthing_scripts/context.py +14 -15
  327. package/pennyfarthing_scripts/deadcode/__init__.py +6 -0
  328. package/pennyfarthing_scripts/deadcode/__main__.py +6 -0
  329. package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
  330. package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
  331. package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
  332. package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
  333. package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
  334. package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
  335. package/pennyfarthing_scripts/deadcode/analyze.py +322 -0
  336. package/pennyfarthing_scripts/deadcode/cli.py +163 -0
  337. package/pennyfarthing_scripts/deadcode/formatters.py +106 -0
  338. package/pennyfarthing_scripts/deadcode/models.py +54 -0
  339. package/pennyfarthing_scripts/dependencies/__init__.py +20 -0
  340. package/pennyfarthing_scripts/dependencies/__main__.py +5 -0
  341. package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
  342. package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
  343. package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
  344. package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
  345. package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
  346. package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
  347. package/pennyfarthing_scripts/dependencies/analyze.py +155 -0
  348. package/pennyfarthing_scripts/dependencies/cli.py +76 -0
  349. package/pennyfarthing_scripts/dependencies/formatters.py +63 -0
  350. package/pennyfarthing_scripts/dependencies/models.py +39 -0
  351. package/pennyfarthing_scripts/git/__init__.py +5 -5
  352. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  353. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  354. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  355. package/pennyfarthing_scripts/git/create_branches.py +3 -2
  356. package/pennyfarthing_scripts/git/status_all.py +1 -1
  357. package/pennyfarthing_scripts/healthscore/__init__.py +21 -0
  358. package/pennyfarthing_scripts/healthscore/__main__.py +14 -0
  359. package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
  360. package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
  361. package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
  362. package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
  363. package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
  364. package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
  365. package/pennyfarthing_scripts/healthscore/analyze.py +591 -0
  366. package/pennyfarthing_scripts/healthscore/cli.py +80 -0
  367. package/pennyfarthing_scripts/healthscore/formatters.py +46 -0
  368. package/pennyfarthing_scripts/healthscore/models.py +43 -0
  369. package/pennyfarthing_scripts/hooks/cyclist-pretooluse-hook.sh +0 -0
  370. package/pennyfarthing_scripts/hooks.py +8 -11
  371. package/pennyfarthing_scripts/hotspots/__init__.py +6 -6
  372. package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
  373. package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
  374. package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
  375. package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
  376. package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
  377. package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
  378. package/pennyfarthing_scripts/hotspots/analyze.py +155 -14
  379. package/pennyfarthing_scripts/hotspots/cli.py +12 -10
  380. package/pennyfarthing_scripts/hotspots/models.py +0 -1
  381. package/pennyfarthing_scripts/jira/__init__.py +15 -17
  382. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  383. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  384. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  385. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  386. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  387. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  388. package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
  389. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  390. package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
  391. package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
  392. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  393. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  394. package/pennyfarthing_scripts/jira/bidirectional.py +44 -18
  395. package/pennyfarthing_scripts/jira/claim.py +21 -0
  396. package/pennyfarthing_scripts/jira/cli.py +6 -3
  397. package/pennyfarthing_scripts/jira/client.py +32 -4
  398. package/pennyfarthing_scripts/jira/create.py +45 -1
  399. package/pennyfarthing_scripts/jira/epic.py +3 -2
  400. package/pennyfarthing_scripts/jira/reconcile.py +0 -1
  401. package/pennyfarthing_scripts/jira/story.py +2 -0
  402. package/pennyfarthing_scripts/jira/sync.py +1 -1
  403. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  404. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  405. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  406. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  407. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  408. package/pennyfarthing_scripts/migration/skill.py +0 -1
  409. package/pennyfarthing_scripts/migration/step.py +0 -1
  410. package/pennyfarthing_scripts/migration/validate.py +8 -5
  411. package/pennyfarthing_scripts/patch_mode.py +2 -2
  412. package/pennyfarthing_scripts/preflight/__init__.py +1 -1
  413. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  414. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  415. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  416. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  417. package/pennyfarthing_scripts/preflight/finish.py +0 -1
  418. package/pennyfarthing_scripts/pretooluse_hook.py +6 -7
  419. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  420. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  421. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  422. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  423. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  424. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  425. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  426. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  427. package/pennyfarthing_scripts/prime/cli.py +5 -1
  428. package/pennyfarthing_scripts/prime/loader.py +2 -3
  429. package/pennyfarthing_scripts/prime/persona.py +2 -1
  430. package/pennyfarthing_scripts/prime/tiers.py +4 -4
  431. package/pennyfarthing_scripts/schema_validation_hook.py +2 -3
  432. package/pennyfarthing_scripts/sprint/__init__.py +10 -12
  433. package/pennyfarthing_scripts/sprint/__main__.py +2 -2
  434. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  435. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  436. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  437. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  438. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  439. package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
  440. package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
  441. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  442. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  443. package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
  444. package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
  445. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  446. package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
  447. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  448. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  449. package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
  450. package/pennyfarthing_scripts/sprint/archive.py +0 -1
  451. package/pennyfarthing_scripts/sprint/archive_epic.py +198 -97
  452. package/pennyfarthing_scripts/sprint/cli.py +62 -46
  453. package/pennyfarthing_scripts/sprint/epic_add.py +8 -1
  454. package/pennyfarthing_scripts/sprint/import_epic.py +42 -18
  455. package/pennyfarthing_scripts/sprint/loader.py +6 -0
  456. package/pennyfarthing_scripts/sprint/status.py +1 -2
  457. package/pennyfarthing_scripts/sprint/story_add.py +202 -27
  458. package/pennyfarthing_scripts/sprint/story_finish.py +209 -0
  459. package/pennyfarthing_scripts/sprint/story_update.py +11 -3
  460. package/pennyfarthing_scripts/sprint/validate_cmd.py +0 -1
  461. package/pennyfarthing_scripts/sprint/validator.py +120 -6
  462. package/pennyfarthing_scripts/sprint/work.py +28 -7
  463. package/pennyfarthing_scripts/sprint/yaml_io.py +10 -2
  464. package/pennyfarthing_scripts/story/__init__.py +14 -16
  465. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  466. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  467. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  468. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  469. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  470. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  471. package/pennyfarthing_scripts/story/size.py +0 -1
  472. package/pennyfarthing_scripts/story/template.py +0 -1
  473. package/pennyfarthing_scripts/swebench.py +1 -2
  474. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  475. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  476. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  477. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  478. package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
  479. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  480. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  481. package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
  482. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  483. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  484. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  485. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  486. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  487. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  488. package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
  489. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  490. package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
  491. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  492. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  493. package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
  494. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  495. package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
  496. package/pennyfarthing_scripts/tests/conftest.py +1 -2
  497. package/pennyfarthing_scripts/tests/test_brownfield.py +10 -13
  498. package/pennyfarthing_scripts/tests/test_cli_modules.py +0 -4
  499. package/pennyfarthing_scripts/tests/test_codemarkers.py +687 -0
  500. package/pennyfarthing_scripts/tests/test_common.py +9 -4
  501. package/pennyfarthing_scripts/tests/test_epic_shard_validation.py +699 -0
  502. package/pennyfarthing_scripts/tests/test_git_utils.py +10 -13
  503. package/pennyfarthing_scripts/tests/test_healthscore.py +516 -0
  504. package/pennyfarthing_scripts/tests/test_jira_package.py +0 -3
  505. package/pennyfarthing_scripts/tests/test_package_structure.py +3 -16
  506. package/pennyfarthing_scripts/tests/test_patch_mode.py +7 -11
  507. package/pennyfarthing_scripts/tests/test_prime.py +39 -21
  508. package/pennyfarthing_scripts/tests/test_sprint_package.py +3 -8
  509. package/pennyfarthing_scripts/tests/test_sprint_validator.py +53 -5
  510. package/pennyfarthing_scripts/tests/test_story_add.py +3 -7
  511. package/pennyfarthing_scripts/tests/test_story_package.py +0 -3
  512. package/pennyfarthing_scripts/tests/test_story_update.py +5 -10
  513. package/pennyfarthing_scripts/tests/test_tiers.py +18 -17
  514. package/pennyfarthing_scripts/tests/test_token_counting.py +19 -13
  515. package/pennyfarthing_scripts/tests/test_validate_cmd.py +2 -7
  516. package/pennyfarthing_scripts/tests/test_workflow_check.py +0 -2
  517. package/pennyfarthing_scripts/tests/test_yaml_io.py +0 -3
  518. package/pennyfarthing_scripts/theme/__init__.py +5 -0
  519. package/pennyfarthing_scripts/theme/__main__.py +6 -0
  520. package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
  521. package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
  522. package/pennyfarthing_scripts/theme/cli.py +287 -0
  523. package/pennyfarthing_scripts/validate/__init__.py +21 -0
  524. package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
  525. package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
  526. package/pennyfarthing_scripts/validate/adapters/__init__.py +0 -0
  527. package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  528. package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
  529. package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
  530. package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
  531. package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
  532. package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
  533. package/pennyfarthing_scripts/validate/adapters/agent.py +239 -0
  534. package/pennyfarthing_scripts/validate/adapters/schema.py +30 -0
  535. package/pennyfarthing_scripts/validate/adapters/skill_command.py +292 -0
  536. package/pennyfarthing_scripts/validate/adapters/sprint.py +69 -0
  537. package/pennyfarthing_scripts/validate/adapters/workflow.py +320 -0
  538. package/pennyfarthing_scripts/validate/cli.py +141 -0
  539. package/pennyfarthing_scripts/welcome_hook.py +2 -3
  540. package/pennyfarthing_scripts/workflow.py +3 -3
  541. package/scripts/README.md +41 -0
  542. package/pennyfarthing-dist/agents/workflow-status-check.md +0 -96
  543. package/pennyfarthing-dist/commands/benchmark-control.md +0 -69
  544. package/pennyfarthing-dist/commands/benchmark.md +0 -485
  545. package/pennyfarthing-dist/commands/job-fair.md +0 -102
  546. package/pennyfarthing-dist/commands/solo.md +0 -447
  547. package/pennyfarthing-dist/guides/benchmarks.md +0 -62
  548. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  549. package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +0 -59
  550. package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +0 -220
  551. package/pennyfarthing-dist/scripts/test/swebench-judge.py +0 -374
  552. package/pennyfarthing-dist/scripts/test/test-cache.sh +0 -165
  553. package/pennyfarthing-dist/scripts/test/test-setup.sh +0 -337
  554. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +0 -13
  555. package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +0 -402
  556. package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +0 -97
  557. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +0 -261
  558. package/pennyfarthing-dist/skills/judge/SKILL.md +0 -644
  559. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +0 -187
  560. package/pennyfarthing-dist/workflows/dev-story/checklist.md +0 -80
  561. package/pennyfarthing-dist/workflows/dev-story/instructions.xml +0 -410
  562. package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +0 -50
  563. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +0 -201
  564. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +0 -156
  565. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +0 -140
  566. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +0 -203
  567. package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +0 -74
  568. package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +0 -27
  569. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  570. package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
  571. package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
  572. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  573. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  574. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  575. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  576. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  577. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  578. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  579. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  580. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
@@ -28,11 +28,10 @@ from dataclasses import dataclass, field
28
28
  from pathlib import Path
29
29
  from typing import Any, Literal
30
30
 
31
- from pennyfarthing_scripts.jira.client import JiraClient, map_jira_to_status, map_status_to_jira
32
31
  from pennyfarthing_scripts.common.output import error, info, success, warn
32
+ from pennyfarthing_scripts.jira.client import JiraClient, map_jira_to_status, map_status_to_jira
33
33
  from pennyfarthing_scripts.sprint.loader import get_all_stories, load_sprint
34
34
 
35
-
36
35
  # =============================================================================
37
36
  # Data Classes
38
37
  # =============================================================================
@@ -43,7 +42,7 @@ class SyncChange:
43
42
  """Represents a single sync change to apply."""
44
43
 
45
44
  key: str
46
- field: Literal["status", "points"]
45
+ field: Literal["status", "points", "assigned_to"]
47
46
  action: Literal["update-yaml", "update-jira"]
48
47
  yaml_value: Any
49
48
  jira_value: Any
@@ -123,10 +122,15 @@ Examples:
123
122
  action="store_true",
124
123
  help="Sync story points",
125
124
  )
125
+ parser.add_argument(
126
+ "--assignee",
127
+ action="store_true",
128
+ help="Sync assignee field (Jira -> YAML only)",
129
+ )
126
130
  parser.add_argument(
127
131
  "--all",
128
132
  action="store_true",
129
- help="Sync all fields (status + points)",
133
+ help="Sync all fields (status + points + assignee)",
130
134
  )
131
135
  parser.add_argument(
132
136
  "--sprint",
@@ -137,10 +141,11 @@ Examples:
137
141
 
138
142
  args = parser.parse_args(argv)
139
143
 
140
- # --all implies both --status and --points
144
+ # --all implies --status, --points, and --assignee
141
145
  if args.all:
142
146
  args.status = True
143
147
  args.points = True
148
+ args.assignee = True
144
149
 
145
150
  return args
146
151
 
@@ -156,6 +161,7 @@ def generate_sync_plan(
156
161
  *,
157
162
  sync_status: bool = False,
158
163
  sync_points: bool = False,
164
+ sync_assignee: bool = False,
159
165
  yaml_wins: bool = False,
160
166
  ) -> SyncPlan:
161
167
  """Generate a sync plan comparing YAML and Jira stories.
@@ -165,6 +171,7 @@ def generate_sync_plan(
165
171
  jira_stories: Stories from Jira [{key, fields: {status: {name}, customfield_10031, ...}}]
166
172
  sync_status: Whether to sync status field
167
173
  sync_points: Whether to sync points field
174
+ sync_assignee: Whether to sync assignee field (always Jira -> YAML)
168
175
  yaml_wins: If True, YAML wins conflicts (default: Jira wins)
169
176
 
170
177
  Returns:
@@ -248,6 +255,26 @@ def generate_sync_plan(
248
255
  )
249
256
  )
250
257
 
258
+ # Check assignee differences (always Jira -> YAML, ignores yaml_wins)
259
+ if sync_assignee:
260
+ yaml_assignee = yaml_story.get("assigned_to")
261
+ jira_assignee_obj = jira_story.get("fields", {}).get("assignee")
262
+ jira_assignee_email = (
263
+ jira_assignee_obj.get("emailAddress") if jira_assignee_obj else None
264
+ )
265
+
266
+ if yaml_assignee != jira_assignee_email:
267
+ plan.changes.append(
268
+ SyncChange(
269
+ key=key,
270
+ field="assigned_to",
271
+ action="update-yaml",
272
+ yaml_value=yaml_assignee,
273
+ jira_value=jira_assignee_email,
274
+ target_value=jira_assignee_email,
275
+ )
276
+ )
277
+
251
278
  return plan
252
279
 
253
280
 
@@ -326,21 +353,17 @@ async def execute_sync_plan(
326
353
 
327
354
  # Execute YAML updates (sequential, file-based)
328
355
  if yaml_updates:
329
- # Load current sprint data
330
356
  from pennyfarthing_scripts.common.config import get_project_root
357
+ from pennyfarthing_scripts.sprint.yaml_io import read_sprint, write_sprint
331
358
 
332
359
  root = get_project_root()
333
360
  sprint_file = sprint_path or (root / "sprint" / "current-sprint.yaml")
334
361
 
335
362
  if sprint_file.exists():
336
- import yaml
337
-
338
- with open(sprint_file) as f:
339
- sprint_data = yaml.safe_load(f)
363
+ sprint_data = read_sprint(sprint_file)
340
364
 
341
365
  # Apply YAML updates
342
366
  for change in yaml_updates:
343
- # Find and update the story in sprint data
344
367
  updated = _update_story_in_sprint(
345
368
  sprint_data, change.key, change.field, change.target_value
346
369
  )
@@ -348,10 +371,9 @@ async def execute_sync_plan(
348
371
  result.changes_applied += 1
349
372
  result.yaml_modified = True
350
373
 
351
- # Write back if modified
374
+ # Write back if modified (handles shards automatically)
352
375
  if result.yaml_modified:
353
- with open(sprint_file, "w") as f:
354
- yaml.dump(sprint_data, f, default_flow_style=False, sort_keys=False)
376
+ write_sprint(sprint_file, sprint_data)
355
377
 
356
378
  return result
357
379
 
@@ -379,7 +401,10 @@ def _update_story_in_sprint(
379
401
  for epic in sprint_data.get("epics", []):
380
402
  for story in epic.get("stories", []):
381
403
  if story.get("jira") == jira_key:
382
- story[field] = value
404
+ if value is None and field in story:
405
+ del story[field]
406
+ elif value is not None:
407
+ story[field] = value
383
408
  return True
384
409
 
385
410
  return False
@@ -465,8 +490,8 @@ async def async_main(args: argparse.Namespace) -> int:
465
490
  Exit code (0 for success, 1 for error)
466
491
  """
467
492
  # Validate at least one field is selected
468
- if not args.status and not args.points:
469
- error("Must specify at least one field to sync: --status, --points, or --all")
493
+ if not args.status and not args.points and not args.assignee:
494
+ error("Must specify at least one field to sync: --status, --points, --assignee, or --all")
470
495
  return 1
471
496
 
472
497
  # Load sprint data
@@ -494,7 +519,7 @@ async def async_main(args: argparse.Namespace) -> int:
494
519
  tasks = [client.get_issue_async(key) for key in jira_keys]
495
520
  results = await asyncio.gather(*tasks, return_exceptions=True)
496
521
 
497
- for key, result in zip(jira_keys, results):
522
+ for key, result in zip(jira_keys, results, strict=False):
498
523
  if isinstance(result, Exception):
499
524
  warn(f"Failed to fetch {key}: {result}")
500
525
  elif result:
@@ -510,6 +535,7 @@ async def async_main(args: argparse.Namespace) -> int:
510
535
  jira_stories,
511
536
  sync_status=args.status,
512
537
  sync_points=args.points,
538
+ sync_assignee=args.assignee,
513
539
  yaml_wins=args.yaml_wins,
514
540
  )
515
541
 
@@ -162,6 +162,27 @@ def claim_story(issue_key: str) -> dict[str, Any]:
162
162
  "exit_code": 3,
163
163
  }
164
164
 
165
+ # Update sprint YAML assigned_to field
166
+ try:
167
+ from pennyfarthing_scripts.common.config import get_project_root
168
+ from pennyfarthing_scripts.sprint.yaml_io import read_sprint, write_sprint
169
+
170
+ root = get_project_root()
171
+ sprint_path = root / "sprint" / "current-sprint.yaml"
172
+ if sprint_path.exists():
173
+ data = read_sprint(sprint_path)
174
+ for epic in data.get("epics", []):
175
+ if not isinstance(epic, dict):
176
+ continue
177
+ for story in epic.get("stories", []):
178
+ if story.get("jira") == issue_key:
179
+ story["assigned_to"] = current_user
180
+ write_sprint(sprint_path, data)
181
+ actions.append("Sprint YAML assigned_to set")
182
+ break
183
+ except Exception:
184
+ pass # Best-effort — Jira claim already succeeded
185
+
165
186
  return {
166
187
  "success": True,
167
188
  "actions": actions,
@@ -206,7 +206,7 @@ def create_standalone(title, points, description, dry_run):
206
206
  click.echo(f"[DRY-RUN] Would create: {title}")
207
207
  click.echo(f" Points: {points}")
208
208
  click.echo(f" Sprint: {sprint_id}")
209
- click.echo(f" Actions: create -> add to sprint -> transition to Done")
209
+ click.echo(" Actions: create -> add to sprint -> transition to Done")
210
210
  return
211
211
 
212
212
  client = get_client()
@@ -241,7 +241,7 @@ def create_standalone(title, points, description, dry_run):
241
241
  # 4. Transition to Done
242
242
  result = client.transition_sync(jira_key, "Done")
243
243
  if result.get("success"):
244
- click.echo(f"Transitioned to Done")
244
+ click.echo("Transitioned to Done")
245
245
  else:
246
246
  click.echo(f"Warning: could not transition to Done: {result.get('reason')}")
247
247
 
@@ -274,9 +274,10 @@ def sync(epic, dry_run, transition, points, sync_all):
274
274
  @click.option("--yaml-wins", is_flag=True, help="Prefer YAML values on conflict")
275
275
  @click.option("--status", is_flag=True, help="Sync status field")
276
276
  @click.option("--points", is_flag=True, help="Sync story points")
277
+ @click.option("--assignee", is_flag=True, help="Sync assignee field (Jira -> YAML only)")
277
278
  @click.option("--all", "sync_all", is_flag=True, help="Sync all fields")
278
279
  @click.option("--sprint", "sprint_id", help="Target specific sprint")
279
- def bidirectional(dry_run, yaml_wins, status, points, sync_all, sprint_id):
280
+ def bidirectional(dry_run, yaml_wins, status, points, assignee, sync_all, sprint_id):
280
281
  """Bidirectional sync between YAML and Jira."""
281
282
  from pennyfarthing_scripts.jira.bidirectional import main as bidirectional_main
282
283
 
@@ -289,6 +290,8 @@ def bidirectional(dry_run, yaml_wins, status, points, sync_all, sprint_id):
289
290
  args.append("--status")
290
291
  if points or sync_all:
291
292
  args.append("--points")
293
+ if assignee or sync_all:
294
+ args.append("--assignee")
292
295
  if sync_all:
293
296
  args.append("--all")
294
297
  if sprint_id:
@@ -301,6 +301,34 @@ def map_github_to_jira(github_user: str | None) -> str | None:
301
301
  return GITHUB_TO_JIRA_MAP.get(github_user, f"{github_user}@1898andco.io")
302
302
 
303
303
 
304
+ def get_current_user_email() -> str:
305
+ """Get the current user's Jira email address.
306
+
307
+ Resolution order:
308
+ 1. JIRA_USER environment variable
309
+ 2. git config user.email
310
+ 3. Default fallback
311
+
312
+ Returns:
313
+ Email address string
314
+ """
315
+ jira_user = os.environ.get("JIRA_USER")
316
+ if jira_user:
317
+ return jira_user
318
+
319
+ try:
320
+ result = subprocess.run(
321
+ ["git", "config", "user.email"],
322
+ capture_output=True, text=True, timeout=5,
323
+ )
324
+ if result.returncode == 0 and result.stdout.strip():
325
+ return result.stdout.strip()
326
+ except Exception:
327
+ pass
328
+
329
+ return "keith.avery@1898andco.io"
330
+
331
+
304
332
  # =============================================================================
305
333
  # JiraClient - Unified REST API client
306
334
  # =============================================================================
@@ -487,7 +515,7 @@ class JiraClient:
487
515
  f"Available: {available}",
488
516
  }
489
517
 
490
- result = self._call_api_sync(
518
+ self._call_api_sync(
491
519
  "POST",
492
520
  f"/rest/api/3/issue/{issue_key}/transitions",
493
521
  {"transition": {"id": transition_id}},
@@ -525,7 +553,7 @@ class JiraClient:
525
553
  account_id = None
526
554
 
527
555
  payload = {"accountId": account_id}
528
- result = self._call_api_sync(
556
+ self._call_api_sync(
529
557
  "PUT", f"/rest/api/3/issue/{issue_key}/assignee", payload
530
558
  )
531
559
  # Assign PUT returns empty body on success (204)
@@ -541,7 +569,7 @@ class JiraClient:
541
569
  Returns:
542
570
  Result dict with success status
543
571
  """
544
- result = self._call_api_sync(
572
+ self._call_api_sync(
545
573
  "POST",
546
574
  f"/rest/agile/1.0/sprint/{sprint_id}/issue",
547
575
  {"issues": [issue_key]},
@@ -591,7 +619,7 @@ class JiraClient:
591
619
  Returns:
592
620
  Result dict with success status
593
621
  """
594
- result = self._call_api_sync(
622
+ self._call_api_sync(
595
623
  "POST",
596
624
  "/rest/api/3/issueLink",
597
625
  {
@@ -16,7 +16,7 @@ import sys
16
16
  from pathlib import Path
17
17
  from typing import Any
18
18
 
19
- from pennyfarthing_scripts.jira.client import JIRA_PROJECT, JiraClient, get_client
19
+ from pennyfarthing_scripts.jira.client import JIRA_PROJECT, get_client
20
20
  from pennyfarthing_scripts.sprint.loader import find_epic, find_story, load_sprint
21
21
  from pennyfarthing_scripts.sprint.yaml_io import read_sprint, write_sprint
22
22
 
@@ -150,6 +150,7 @@ def create_epic_in_jira(
150
150
  *,
151
151
  sprint_path: Path | None = None,
152
152
  dry_run: bool = False,
153
+ force: bool = False,
153
154
  ) -> dict[str, Any]:
154
155
  """Create a Jira epic and its child stories from sprint YAML.
155
156
 
@@ -157,6 +158,7 @@ def create_epic_in_jira(
157
158
  epic_id: Epic ID from sprint YAML (e.g., "epic-63" or "63")
158
159
  sprint_path: Path to sprint YAML (defaults to auto-detect)
159
160
  dry_run: If True, preview without creating
161
+ force: If True, create even if duplicate title detected
160
162
 
161
163
  Returns:
162
164
  {success, epic_key?, stories: [{id, jira_key}], error?}
@@ -184,6 +186,13 @@ def create_epic_in_jira(
184
186
  if not epic_ruamel:
185
187
  return {"success": False, "error": f"Epic '{epic_id}' not found in ruamel data"}
186
188
 
189
+ # Validate epic shard before any Jira operations (ADR-0022)
190
+ from pennyfarthing_scripts.sprint.validator import validate_epic_shard
191
+ validation = validate_epic_shard(dict(epic_ruamel))
192
+ if not validation.valid:
193
+ error_msgs = "; ".join(e.message for e in validation.errors)
194
+ return {"success": False, "error": f"Epic validation failed: {error_msgs}"}
195
+
187
196
  title = epic.get("title", f"Epic {epic_id}")
188
197
  description = epic.get("description", "")
189
198
  epic_jira_key = epic.get("jira")
@@ -200,6 +209,41 @@ def create_epic_in_jira(
200
209
  epic_jira_key = "MSSCI-XXXXX"
201
210
  else:
202
211
  client = get_client()
212
+
213
+ # Idempotency check: search for existing epic with same title (ADR-0022)
214
+ try:
215
+ existing = client.search_issues_sync(
216
+ f'project = {JIRA_PROJECT} AND issuetype = Epic AND summary ~ "{title}"'
217
+ )
218
+ if existing and not force:
219
+ existing_key = existing[0]["key"]
220
+ print(f"Found existing epic with same title: {existing_key}")
221
+ epic_jira_key = existing_key
222
+
223
+ # Update YAML with existing key
224
+ epic_ruamel["jira"] = epic_jira_key
225
+ write_sprint(path, data)
226
+
227
+ return {
228
+ "success": True,
229
+ "epic_key": epic_jira_key,
230
+ "duplicate_detected": True,
231
+ "stories": [],
232
+ }
233
+ elif existing and force:
234
+ import warnings
235
+ warnings.warn(
236
+ f"Duplicate epic title detected ({existing[0]['key']}), "
237
+ "proceeding with --force",
238
+ stacklevel=2,
239
+ )
240
+ except Exception as exc:
241
+ import warnings
242
+ warnings.warn(
243
+ f"Jira search for duplicate titles failed: {exc}",
244
+ stacklevel=2,
245
+ )
246
+
203
247
  payload = {
204
248
  "fields": {
205
249
  "project": {"key": JIRA_PROJECT},
@@ -17,8 +17,9 @@ import json
17
17
  import sys
18
18
  from typing import Any
19
19
 
20
- from pennyfarthing_scripts.jira.client import JiraClient, JIRA_PROJECT
21
- from pennyfarthing_scripts.sprint.loader import find_epic, load_sprint as load_current_sprint
20
+ from pennyfarthing_scripts.jira.client import JIRA_PROJECT, JiraClient
21
+ from pennyfarthing_scripts.sprint.loader import find_epic
22
+ from pennyfarthing_scripts.sprint.loader import load_sprint as load_current_sprint
22
23
 
23
24
 
24
25
  def parse_args(args: list[str] | None = None) -> argparse.Namespace:
@@ -23,7 +23,6 @@ from pennyfarthing_scripts.jira.client import (
23
23
  JIRA_PROJECT,
24
24
  get_client,
25
25
  get_jira_field,
26
- map_jira_to_status,
27
26
  map_status_to_jira,
28
27
  )
29
28
  from pennyfarthing_scripts.sprint.loader import load_sprint
@@ -24,6 +24,8 @@ from pennyfarthing_scripts.sprint.loader import (
24
24
  find_epic,
25
25
  find_story,
26
26
  get_story_by_id,
27
+ )
28
+ from pennyfarthing_scripts.sprint.loader import (
27
29
  load_sprint as load_current_sprint,
28
30
  )
29
31
 
@@ -17,13 +17,13 @@ from dataclasses import dataclass, field
17
17
  from typing import Any
18
18
 
19
19
  from pennyfarthing_scripts.common.config import get_project_root
20
+ from pennyfarthing_scripts.common.output import error, info, success, warn
20
21
  from pennyfarthing_scripts.jira.client import (
21
22
  JiraClient,
22
23
  extract_jira_key,
23
24
  get_jira_field,
24
25
  map_status_to_jira,
25
26
  )
26
- from pennyfarthing_scripts.common.output import error, info, success, warn
27
27
  from pennyfarthing_scripts.sprint.loader import find_epic, load_sprint
28
28
 
29
29
 
@@ -10,7 +10,6 @@ import re
10
10
  from dataclasses import dataclass, field
11
11
  from pathlib import Path
12
12
 
13
-
14
13
  # Tag requirements
15
14
  REQUIRED_TAGS = ["run", "output"]
16
15
  RECOMMENDED_TAGS = ["args", "example", "when"]
@@ -10,7 +10,6 @@ import re
10
10
  from dataclasses import dataclass, field
11
11
  from pathlib import Path
12
12
 
13
-
14
13
  # Tag requirements
15
14
  REQUIRED_TAGS = ["step-meta", "purpose", "instructions", "output"]
16
15
  RECOMMENDED_TAGS = ["prerequisites", "actions", "collaboration-menu", "next-step"]
@@ -20,12 +20,20 @@ from pennyfarthing_scripts.migration.session import (
20
20
  )
21
21
  from pennyfarthing_scripts.migration.skill import (
22
22
  RECOMMENDED_TAGS as SKILL_RECOMMENDED,
23
+ )
24
+ from pennyfarthing_scripts.migration.skill import (
23
25
  REQUIRED_TAGS as SKILL_REQUIRED,
26
+ )
27
+ from pennyfarthing_scripts.migration.skill import (
24
28
  find_skill_files,
25
29
  )
26
30
  from pennyfarthing_scripts.migration.step import (
27
31
  RECOMMENDED_TAGS as STEP_RECOMMENDED,
32
+ )
33
+ from pennyfarthing_scripts.migration.step import (
28
34
  REQUIRED_TAGS as STEP_REQUIRED,
35
+ )
36
+ from pennyfarthing_scripts.migration.step import (
29
37
  STEP_META_FIELDS,
30
38
  find_step_files,
31
39
  )
@@ -119,7 +127,6 @@ def validate_skill_file(file_path: Path) -> ValidationResult:
119
127
  Returns:
120
128
  ValidationResult with errors/warnings
121
129
  """
122
- skill_name = file_path.parent.name
123
130
  result = ValidationResult(file_path=file_path, file_type="skill")
124
131
  content = file_path.read_text()
125
132
 
@@ -157,10 +164,6 @@ def validate_step_file(file_path: Path) -> ValidationResult:
157
164
  result = ValidationResult(file_path=file_path, file_type="step")
158
165
  content = file_path.read_text()
159
166
 
160
- # Determine workflow/step names from path
161
- workflow_name = file_path.parent.parent.name
162
- step_name = file_path.stem
163
-
164
167
  # Check required tags
165
168
  for tag in STEP_REQUIRED:
166
169
  if not _has_tag(content, tag):
@@ -13,7 +13,7 @@ from __future__ import annotations
13
13
  import re
14
14
  import subprocess
15
15
  import time
16
- from dataclasses import dataclass, asdict
16
+ from dataclasses import asdict, dataclass
17
17
  from datetime import datetime
18
18
  from pathlib import Path
19
19
  from typing import Any
@@ -38,7 +38,7 @@ class PatchState:
38
38
  return yaml.dump(asdict(self), default_flow_style=False)
39
39
 
40
40
  @classmethod
41
- def from_yaml(cls, yaml_str: str) -> "PatchState":
41
+ def from_yaml(cls, yaml_str: str) -> PatchState:
42
42
  """Deserialize state from YAML string."""
43
43
  data = yaml.safe_load(yaml_str)
44
44
  return cls(**data)
@@ -5,8 +5,8 @@ to validate story completion before finishing.
5
5
  """
6
6
 
7
7
  from pennyfarthing_scripts.preflight.finish import (
8
- PreflightResult,
9
8
  PreflightIssue,
9
+ PreflightResult,
10
10
  run_finish_preflight,
11
11
  )
12
12
 
@@ -8,7 +8,6 @@ concurrent execution regardless of model behavior.
8
8
  import asyncio
9
9
  import json
10
10
  import re
11
- import sys
12
11
  from dataclasses import dataclass, field
13
12
  from pathlib import Path
14
13
  from typing import Any
@@ -40,15 +40,14 @@ from pathlib import Path
40
40
  sys.path.insert(0, str(Path(__file__).parent))
41
41
 
42
42
  from hooks import (
43
- find_project_root,
44
- get_cyclist_port,
45
- send_to_cyclist,
46
- read_stdin_json,
47
- output_hook_response,
48
43
  HookResponse,
49
- load_settings,
50
- is_cyclist_running,
44
+ find_project_root,
51
45
  get_context_state,
46
+ is_cyclist_running,
47
+ load_settings,
48
+ output_hook_response,
49
+ read_stdin_json,
50
+ send_to_cyclist,
52
51
  )
53
52
 
54
53
 
@@ -22,6 +22,10 @@ import argparse
22
22
  import json
23
23
  import sys
24
24
  from pathlib import Path
25
+ from typing import TYPE_CHECKING
26
+
27
+ if TYPE_CHECKING:
28
+ from typing import Any
25
29
 
26
30
  from pennyfarthing_scripts.common.config import get_project_root
27
31
  from pennyfarthing_scripts.prime.loader import (
@@ -42,7 +46,7 @@ from pennyfarthing_scripts.prime.persona import (
42
46
  load_persona,
43
47
  )
44
48
  from pennyfarthing_scripts.prime.session import cleanup_old_sessions, register_session
45
- from pennyfarthing_scripts.prime.tiers import ContextTier, tier_from_string, load_tier_components
49
+ from pennyfarthing_scripts.prime.tiers import ContextTier, load_tier_components, tier_from_string
46
50
  from pennyfarthing_scripts.prime.workflow import check_redirect, detect_workflow_state
47
51
 
48
52
 
@@ -14,7 +14,6 @@ from __future__ import annotations
14
14
 
15
15
  import re
16
16
  from pathlib import Path
17
- from typing import Any
18
17
 
19
18
  from pennyfarthing_scripts.common.config import get_project_root
20
19
 
@@ -68,7 +67,7 @@ def load_sprint_context(project_root: Path | None = None) -> str | None:
68
67
  Formatted sprint summary, or None if no sprint data
69
68
  """
70
69
  # Import here to avoid circular imports
71
- from pennyfarthing_scripts.sprint.loader import load_sprint, get_sprint_info
70
+ from pennyfarthing_scripts.sprint.loader import load_sprint
72
71
  from pennyfarthing_scripts.sprint.status import get_sprint_status
73
72
 
74
73
  root = project_root or get_project_root()
@@ -136,7 +135,7 @@ def _extract_session_parts(content: str) -> tuple[str, str]:
136
135
 
137
136
  # Header: everything before first ## heading
138
137
  header_lines = []
139
- for i, line in enumerate(lines):
138
+ for line in lines:
140
139
  if line.startswith("## "):
141
140
  break
142
141
  header_lines.append(line)
@@ -14,11 +14,12 @@ import yaml
14
14
  from pennyfarthing_scripts.common.config import get_project_root, load_yaml_config
15
15
  from pennyfarthing_scripts.common.themes import (
16
16
  get_current_theme as _get_current_theme,
17
+ )
18
+ from pennyfarthing_scripts.common.themes import (
17
19
  resolve_theme_path,
18
20
  )
19
21
  from pennyfarthing_scripts.prime.models import CrewMember, Persona
20
22
 
21
-
22
23
  # Standard agent roles for crew manifest
23
24
  AGENT_ROLES = [
24
25
  "sm", "tea", "dev", "reviewer", "architect",