@pennyfarthing/core 9.0.0 → 9.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/README.md +16 -7
  2. package/package.json +1 -1
  3. package/packages/core/dist/cli/commands/doctor.d.ts +5 -2
  4. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  5. package/packages/core/dist/cli/commands/doctor.js +327 -17
  6. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  7. package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
  8. package/packages/core/dist/cli/commands/init.js +3 -246
  9. package/packages/core/dist/cli/commands/init.js.map +1 -1
  10. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  11. package/packages/core/dist/cli/commands/update.js +4 -140
  12. package/packages/core/dist/cli/commands/update.js.map +1 -1
  13. package/packages/core/dist/cli/utils/constants.d.ts +7 -1
  14. package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
  15. package/packages/core/dist/cli/utils/constants.js +2 -0
  16. package/packages/core/dist/cli/utils/constants.js.map +1 -1
  17. package/packages/core/dist/cli/utils/settings.d.ts +22 -0
  18. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -0
  19. package/packages/core/dist/cli/utils/settings.js +300 -0
  20. package/packages/core/dist/cli/utils/settings.js.map +1 -0
  21. package/pennyfarthing-dist/commands/chore.md +18 -17
  22. package/pennyfarthing-dist/commands/continue-session.md +41 -7
  23. package/pennyfarthing-dist/commands/fix-blocker.md +22 -0
  24. package/pennyfarthing-dist/commands/git-cleanup.md +25 -19
  25. package/pennyfarthing-dist/commands/patch.md +210 -0
  26. package/pennyfarthing-dist/commands/setup.md +65 -0
  27. package/pennyfarthing-dist/guides/session-schema.md +346 -0
  28. package/pennyfarthing-dist/guides/skill-schema.md +412 -0
  29. package/pennyfarthing-dist/guides/workflow-step-schema.md +512 -0
  30. package/pennyfarthing-dist/guides/xml-tags.md +292 -0
  31. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  32. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +43 -8
  33. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +30 -0
  34. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +78 -0
  35. package/pennyfarthing-dist/scripts/lib/find-root.sh +32 -7
  36. package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +13 -2
  37. package/pennyfarthing-dist/scripts/sprint/validate-sprint-yaml.sh +139 -0
  38. package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +4 -0
  39. package/pennyfarthing-dist/skills/changelog/SKILL.md +18 -0
  40. package/pennyfarthing-dist/skills/code-review/SKILL.md +5 -1
  41. package/pennyfarthing-dist/skills/context-engineering/SKILL.md +3 -0
  42. package/pennyfarthing-dist/skills/cyclist/SKILL.md +2 -2
  43. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +24 -0
  44. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +3 -0
  45. package/pennyfarthing-dist/skills/judge/SKILL.md +8 -0
  46. package/pennyfarthing-dist/skills/just/SKILL.md +11 -0
  47. package/pennyfarthing-dist/skills/mermaid/SKILL.md +16 -0
  48. package/pennyfarthing-dist/skills/otel/skill.md +4 -0
  49. package/pennyfarthing-dist/skills/permissions/skill.md +3 -0
  50. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +9 -0
  51. package/pennyfarthing-dist/skills/story/skill.md +16 -16
  52. package/pennyfarthing-dist/skills/systematic-debugging/SKILL.md +56 -0
  53. package/pennyfarthing-dist/skills/testing/SKILL.md +22 -0
  54. package/pennyfarthing-dist/skills/theme/skill.md +12 -0
  55. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +4 -0
  56. package/pennyfarthing-dist/skills/workflow/skill.md +22 -14
  57. package/pennyfarthing-dist/skills/yq/SKILL.md +8 -0
  58. package/pennyfarthing-dist/templates/settings.local.json.template +9 -0
  59. package/pennyfarthing-dist/workflows/architecture/steps/step-01-initialize.md +12 -0
  60. package/pennyfarthing-dist/workflows/architecture/steps/step-01b-continue.md +12 -0
  61. package/pennyfarthing-dist/workflows/architecture/steps/step-02-context.md +12 -0
  62. package/pennyfarthing-dist/workflows/architecture/steps/step-03-patterns.md +12 -0
  63. package/pennyfarthing-dist/workflows/architecture/steps/step-04-components.md +12 -0
  64. package/pennyfarthing-dist/workflows/architecture/steps/step-05-interfaces.md +12 -0
  65. package/pennyfarthing-dist/workflows/architecture/steps/step-06-risks.md +12 -0
  66. package/pennyfarthing-dist/workflows/architecture/steps/step-07-document.md +12 -0
  67. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-01-validate-prerequisites.md +25 -0
  68. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-02-design-epics.md +23 -0
  69. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-03-create-stories.md +26 -0
  70. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +24 -0
  71. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +23 -0
  72. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +43 -41
  73. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-02-categorize.md +50 -19
  74. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +102 -111
  75. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +48 -39
  76. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +30 -31
  77. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-01-document-discovery.md +21 -0
  78. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-02-prd-analysis.md +21 -0
  79. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-03-epic-coverage-validation.md +23 -0
  80. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-04-ux-alignment.md +23 -0
  81. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-05-epic-quality-review.md +28 -0
  82. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-06-final-assessment.md +25 -0
  83. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-01-connect.md +257 -0
  84. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-02-explore.md +107 -0
  85. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-03-fix.md +127 -0
  86. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-04-commit.md +122 -0
  87. package/pennyfarthing-dist/workflows/interactive-debug/workflow.yaml +51 -0
  88. package/pennyfarthing-dist/workflows/patch.yaml +2 -3
  89. package/pennyfarthing-dist/workflows/prd/steps-c/step-01-init.md +6 -0
  90. package/pennyfarthing-dist/workflows/prd/steps-c/step-01b-continue.md +6 -0
  91. package/pennyfarthing-dist/workflows/prd/steps-c/step-02-discovery.md +6 -0
  92. package/pennyfarthing-dist/workflows/prd/steps-c/step-03-success.md +6 -0
  93. package/pennyfarthing-dist/workflows/prd/steps-c/step-04-journeys.md +6 -0
  94. package/pennyfarthing-dist/workflows/prd/steps-c/step-05-domain.md +6 -0
  95. package/pennyfarthing-dist/workflows/prd/steps-c/step-06-innovation.md +6 -0
  96. package/pennyfarthing-dist/workflows/prd/steps-c/step-07-project-type.md +6 -0
  97. package/pennyfarthing-dist/workflows/prd/steps-c/step-08-scoping.md +6 -0
  98. package/pennyfarthing-dist/workflows/prd/steps-c/step-09-functional.md +6 -0
  99. package/pennyfarthing-dist/workflows/prd/steps-c/step-10-nonfunctional.md +6 -0
  100. package/pennyfarthing-dist/workflows/prd/steps-c/step-11-polish.md +6 -0
  101. package/pennyfarthing-dist/workflows/prd/steps-c/step-12-complete.md +6 -0
  102. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01-discovery.md +6 -0
  103. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01b-legacy-conversion.md +6 -0
  104. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-02-review.md +6 -0
  105. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-03-edit.md +6 -0
  106. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-04-complete.md +6 -0
  107. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-01-discovery.md +6 -0
  108. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02-format-detection.md +6 -0
  109. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02b-parity-check.md +6 -0
  110. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-03-density-validation.md +6 -0
  111. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +6 -0
  112. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-05-measurability-validation.md +6 -0
  113. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-06-traceability-validation.md +6 -0
  114. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +6 -0
  115. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +6 -0
  116. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-09-project-type-validation.md +6 -0
  117. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-10-smart-validation.md +6 -0
  118. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +6 -0
  119. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-12-completeness-validation.md +6 -0
  120. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-13-report-complete.md +6 -0
  121. package/pennyfarthing-dist/workflows/product-brief/steps/step-01-init.md +18 -0
  122. package/pennyfarthing-dist/workflows/product-brief/steps/step-01b-continue.md +19 -0
  123. package/pennyfarthing-dist/workflows/product-brief/steps/step-02-vision.md +22 -0
  124. package/pennyfarthing-dist/workflows/product-brief/steps/step-03-users.md +22 -0
  125. package/pennyfarthing-dist/workflows/product-brief/steps/step-04-metrics.md +23 -0
  126. package/pennyfarthing-dist/workflows/product-brief/steps/step-05-scope.md +24 -0
  127. package/pennyfarthing-dist/workflows/product-brief/steps/step-06-complete.md +22 -0
  128. package/pennyfarthing-dist/workflows/project-context/steps/step-01-discover.md +22 -0
  129. package/pennyfarthing-dist/workflows/project-context/steps/step-02-generate.md +31 -0
  130. package/pennyfarthing-dist/workflows/project-context/steps/step-03-complete.md +28 -0
  131. package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +157 -0
  132. package/pennyfarthing-dist/workflows/project-setup/steps/step-02-clone-repos.md +217 -0
  133. package/pennyfarthing-dist/workflows/project-setup/steps/step-03-repos-yaml.md +159 -0
  134. package/pennyfarthing-dist/workflows/project-setup/steps/step-04-claude-md.md +186 -0
  135. package/pennyfarthing-dist/workflows/project-setup/steps/step-05-shared-context.md +185 -0
  136. package/pennyfarthing-dist/workflows/project-setup/steps/step-06-task-runner.md +279 -0
  137. package/pennyfarthing-dist/workflows/project-setup/steps/step-07-theme.md +200 -0
  138. package/pennyfarthing-dist/workflows/project-setup/steps/step-08-cyclist.md +245 -0
  139. package/pennyfarthing-dist/workflows/project-setup/steps/step-09-complete.md +203 -0
  140. package/pennyfarthing-dist/workflows/project-setup/workflow.yaml +41 -0
  141. package/pennyfarthing-dist/workflows/quick-dev/steps/step-01-mode-detection.md +21 -0
  142. package/pennyfarthing-dist/workflows/quick-dev/steps/step-02-context-gathering.md +23 -0
  143. package/pennyfarthing-dist/workflows/quick-dev/steps/step-03-execute.md +25 -0
  144. package/pennyfarthing-dist/workflows/quick-dev/steps/step-04-self-check.md +22 -0
  145. package/pennyfarthing-dist/workflows/quick-dev/steps/step-05-adversarial-review.md +23 -0
  146. package/pennyfarthing-dist/workflows/quick-dev/steps/step-06-resolve-findings.md +23 -0
  147. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +12 -0
  148. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +12 -0
  149. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +12 -0
  150. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +12 -0
  151. package/pennyfarthing-dist/workflows/research/steps-domain/step-01-init.md +22 -0
  152. package/pennyfarthing-dist/workflows/research/steps-domain/step-02-domain-analysis.md +24 -0
  153. package/pennyfarthing-dist/workflows/research/steps-domain/step-03-competitive-landscape.md +25 -0
  154. package/pennyfarthing-dist/workflows/research/steps-domain/step-04-regulatory-focus.md +26 -0
  155. package/pennyfarthing-dist/workflows/research/steps-domain/step-05-technical-trends.md +26 -0
  156. package/pennyfarthing-dist/workflows/research/steps-domain/step-06-research-synthesis.md +34 -0
  157. package/pennyfarthing-dist/workflows/research/steps-market/step-01-init.md +23 -0
  158. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-behavior.md +25 -0
  159. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-insights.md +27 -0
  160. package/pennyfarthing-dist/workflows/research/steps-market/step-03-customer-pain-points.md +26 -0
  161. package/pennyfarthing-dist/workflows/research/steps-market/step-04-customer-decisions.md +27 -0
  162. package/pennyfarthing-dist/workflows/research/steps-market/step-05-competitive-analysis.md +26 -0
  163. package/pennyfarthing-dist/workflows/research/steps-market/step-06-research-completion.md +35 -0
  164. package/pennyfarthing-dist/workflows/research/steps-technical/step-01-init.md +22 -0
  165. package/pennyfarthing-dist/workflows/research/steps-technical/step-02-technical-overview.md +25 -0
  166. package/pennyfarthing-dist/workflows/research/steps-technical/step-03-integration-patterns.md +26 -0
  167. package/pennyfarthing-dist/workflows/research/steps-technical/step-04-architectural-patterns.md +26 -0
  168. package/pennyfarthing-dist/workflows/research/steps-technical/step-05-implementation-research.md +29 -1
  169. package/pennyfarthing-dist/workflows/research/steps-technical/step-06-research-synthesis.md +37 -1
  170. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-01-parse-epic-files.md +15 -0
  171. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-02-build-sprint-status.md +17 -0
  172. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-03-status-detection.md +16 -0
  173. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-04-generate-status-file.md +17 -0
  174. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-05-validate-and-report.md +22 -0
  175. package/pennyfarthing-dist/workflows/ux-design/steps/step-01-init.md +6 -0
  176. package/pennyfarthing-dist/workflows/ux-design/steps/step-01b-continue.md +6 -0
  177. package/pennyfarthing-dist/workflows/ux-design/steps/step-02-discovery.md +6 -0
  178. package/pennyfarthing-dist/workflows/ux-design/steps/step-03-core-experience.md +6 -0
  179. package/pennyfarthing-dist/workflows/ux-design/steps/step-04-emotional-response.md +6 -0
  180. package/pennyfarthing-dist/workflows/ux-design/steps/step-05-inspiration.md +6 -0
  181. package/pennyfarthing-dist/workflows/ux-design/steps/step-06-design-system.md +6 -0
  182. package/pennyfarthing-dist/workflows/ux-design/steps/step-07-defining-experience.md +6 -0
  183. package/pennyfarthing-dist/workflows/ux-design/steps/step-08-visual-foundation.md +6 -0
  184. package/pennyfarthing-dist/workflows/ux-design/steps/step-09-design-directions.md +6 -0
  185. package/pennyfarthing-dist/workflows/ux-design/steps/step-10-user-journeys.md +6 -0
  186. package/pennyfarthing-dist/workflows/ux-design/steps/step-11-component-strategy.md +6 -0
  187. package/pennyfarthing-dist/workflows/ux-design/steps/step-12-ux-patterns.md +6 -0
  188. package/pennyfarthing-dist/workflows/ux-design/steps/step-13-responsive-accessibility.md +6 -0
  189. package/pennyfarthing-dist/workflows/ux-design/steps/step-14-complete.md +6 -0
  190. package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  191. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  192. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  193. package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
  194. package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
  195. package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
  196. package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
  197. package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
  198. package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
  199. package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
  200. package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
  201. package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
  202. package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
  203. package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
  204. package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
  205. package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
  206. package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
  207. package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
  208. package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
  209. package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
  210. package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
  211. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  212. package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
  213. package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
  214. package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
  215. package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
  216. package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
  217. package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
  218. package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
  219. package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
  220. package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
  221. package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
  222. package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
  223. package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
  224. package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
  225. package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
  226. package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
  227. package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
  228. package/pennyfarthing_scripts/migration/__init__.py +39 -0
  229. package/pennyfarthing_scripts/migration/__main__.py +10 -0
  230. package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
  231. package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
  232. package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
  233. package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
  234. package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
  235. package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
  236. package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
  237. package/pennyfarthing_scripts/migration/cli.py +304 -0
  238. package/pennyfarthing_scripts/migration/session.py +384 -0
  239. package/pennyfarthing_scripts/migration/skill.py +188 -0
  240. package/pennyfarthing_scripts/migration/step.py +229 -0
  241. package/pennyfarthing_scripts/migration/validate.py +282 -0
  242. package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
  243. package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
  244. package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
  245. package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
  246. package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
  247. package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
  248. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  249. package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
  250. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  251. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  252. package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
  253. package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
  254. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  255. package/pennyfarthing_scripts/schema_validation_hook.py +306 -0
  256. package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
  257. package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
  258. package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
  259. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  260. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  261. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  262. package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
  263. package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
  264. package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
  265. package/pennyfarthing_scripts/sprint/archive_epic.py +399 -0
  266. package/pennyfarthing_scripts/sprint/cli.py +100 -0
  267. package/pennyfarthing_scripts/sprint/import_epic.py +431 -0
  268. package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
  269. package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
  270. package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
  271. package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
  272. package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
  273. package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
  274. package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
  275. package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
  276. package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
  277. package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
  278. package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
  279. package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
  280. package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
  281. package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
  282. package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
  283. package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
  284. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
  285. package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
  286. package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
  287. package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
  288. package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
  289. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
  290. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
  291. package/pennyfarthing-dist/scripts/sprint/import-epic-to-future.sh +0 -10
  292. package/pennyfarthing-dist/scripts/sprint/import_epic_to_future.py +0 -270
@@ -0,0 +1,229 @@
1
+ """
2
+ Workflow step file auditing tools.
3
+
4
+ Audits workflow step files for conformance to guides/workflow-step-schema.md.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from dataclasses import dataclass, field
11
+ from pathlib import Path
12
+
13
+
14
+ # Tag requirements
15
+ REQUIRED_TAGS = ["step-meta", "purpose", "instructions", "output"]
16
+ RECOMMENDED_TAGS = ["prerequisites", "actions", "collaboration-menu", "next-step"]
17
+ OPTIONAL_TAGS = ["gate"]
18
+
19
+ # step-meta required fields
20
+ STEP_META_FIELDS = ["number", "name", "gate"]
21
+
22
+
23
+ @dataclass
24
+ class StepAuditResult:
25
+ """Result of auditing a workflow step file."""
26
+
27
+ workflow_name: str
28
+ step_name: str
29
+ file_path: Path
30
+ missing_required: list[str] = field(default_factory=list)
31
+ missing_recommended: list[str] = field(default_factory=list)
32
+ missing_meta_fields: list[str] = field(default_factory=list)
33
+ present_tags: list[str] = field(default_factory=list)
34
+
35
+ @property
36
+ def is_valid(self) -> bool:
37
+ """Check if step passes validation (has all required)."""
38
+ return len(self.missing_required) == 0 and len(self.missing_meta_fields) == 0
39
+
40
+ @property
41
+ def status(self) -> str:
42
+ """Get status string."""
43
+ if not self.is_valid:
44
+ return "NEEDS UPDATE"
45
+ if self.missing_recommended:
46
+ return "PARTIAL"
47
+ return "OK"
48
+
49
+
50
+ def _has_tag(content: str, tag: str) -> bool:
51
+ """Check if content contains a specific XML tag."""
52
+ return f"<{tag}>" in content or f"<{tag} " in content
53
+
54
+
55
+ def _check_step_meta_fields(content: str) -> list[str]:
56
+ """Check which step-meta fields are missing."""
57
+ # Extract step-meta section
58
+ meta_match = re.search(r"<step-meta>(.+?)</step-meta>", content, re.DOTALL)
59
+ if not meta_match:
60
+ return STEP_META_FIELDS.copy()
61
+
62
+ meta_content = meta_match.group(1)
63
+ missing = []
64
+
65
+ for field_name in STEP_META_FIELDS:
66
+ if f"{field_name}:" not in meta_content:
67
+ missing.append(field_name)
68
+
69
+ return missing
70
+
71
+
72
+ def audit_step_file(file_path: Path) -> StepAuditResult:
73
+ """Audit a single workflow step file.
74
+
75
+ Args:
76
+ file_path: Path to step-*.md file
77
+
78
+ Returns:
79
+ StepAuditResult with findings
80
+ """
81
+ # Determine workflow name from path
82
+ # Could be workflows/{name}/steps/step-*.md
83
+ # or workflows/{name}/steps-{mode}/step-*.md
84
+ steps_dir = file_path.parent
85
+ workflow_dir = steps_dir.parent
86
+ workflow_name = workflow_dir.name
87
+ step_name = file_path.stem
88
+
89
+ content = file_path.read_text()
90
+
91
+ result = StepAuditResult(
92
+ workflow_name=workflow_name, step_name=step_name, file_path=file_path
93
+ )
94
+
95
+ # Check required tags
96
+ for tag in REQUIRED_TAGS:
97
+ if _has_tag(content, tag):
98
+ result.present_tags.append(tag)
99
+ else:
100
+ result.missing_required.append(tag)
101
+
102
+ # Check step-meta fields if tag exists
103
+ if "step-meta" in result.present_tags:
104
+ result.missing_meta_fields = _check_step_meta_fields(content)
105
+ if result.missing_meta_fields:
106
+ # Add to required as "step-meta fields: x, y"
107
+ missing_str = ", ".join(result.missing_meta_fields)
108
+ result.missing_required.append(f"step-meta fields ({missing_str})")
109
+
110
+ # Check recommended tags
111
+ for tag in RECOMMENDED_TAGS:
112
+ if _has_tag(content, tag):
113
+ result.present_tags.append(tag)
114
+ else:
115
+ result.missing_recommended.append(tag)
116
+
117
+ # Check optional tags (just track presence)
118
+ for tag in OPTIONAL_TAGS:
119
+ if _has_tag(content, tag):
120
+ result.present_tags.append(tag)
121
+
122
+ return result
123
+
124
+
125
+ def find_step_files(root: Path) -> list[Path]:
126
+ """Find all workflow step files in a project.
127
+
128
+ Args:
129
+ root: Project root directory
130
+
131
+ Returns:
132
+ List of step-*.md file paths
133
+ """
134
+ # Try multiple locations
135
+ workflow_dirs = [
136
+ root / ".pennyfarthing" / "workflows",
137
+ root / "pennyfarthing" / "pennyfarthing-dist" / "workflows",
138
+ root / "pennyfarthing-dist" / "workflows",
139
+ ]
140
+
141
+ step_files = []
142
+
143
+ for workflows_dir in workflow_dirs:
144
+ if workflows_dir.exists():
145
+ # Find step files in steps/ and steps-*/ directories
146
+ for workflow_dir in workflows_dir.iterdir():
147
+ if not workflow_dir.is_dir():
148
+ continue
149
+
150
+ for steps_dir in workflow_dir.iterdir():
151
+ if steps_dir.is_dir() and steps_dir.name.startswith("steps"):
152
+ step_files.extend(steps_dir.glob("step-*.md"))
153
+
154
+ break # Only use first found workflows dir
155
+
156
+ return sorted(step_files)
157
+
158
+
159
+ @dataclass
160
+ class WorkflowAuditResult:
161
+ """Result of auditing a workflow's step files."""
162
+
163
+ workflow_name: str
164
+ step_results: list[StepAuditResult] = field(default_factory=list)
165
+
166
+ @property
167
+ def total_steps(self) -> int:
168
+ return len(self.step_results)
169
+
170
+ @property
171
+ def valid_steps(self) -> int:
172
+ return sum(1 for r in self.step_results if r.is_valid)
173
+
174
+ @property
175
+ def needs_update(self) -> int:
176
+ return sum(1 for r in self.step_results if not r.is_valid)
177
+
178
+
179
+ def audit_workflow_steps(
180
+ root: Path, *, workflow_name: str | None = None
181
+ ) -> dict[str, list | dict]:
182
+ """Audit workflow step files in a project.
183
+
184
+ Args:
185
+ root: Project root directory
186
+ workflow_name: Optional specific workflow to audit
187
+
188
+ Returns:
189
+ Dict with 'workflows', 'summary' keys
190
+ """
191
+ step_files = find_step_files(root)
192
+
193
+ # Group by workflow
194
+ workflows: dict[str, WorkflowAuditResult] = {}
195
+
196
+ for file_path in step_files:
197
+ result = audit_step_file(file_path)
198
+
199
+ if workflow_name and result.workflow_name != workflow_name:
200
+ continue
201
+
202
+ if result.workflow_name not in workflows:
203
+ workflows[result.workflow_name] = WorkflowAuditResult(
204
+ workflow_name=result.workflow_name
205
+ )
206
+
207
+ workflows[result.workflow_name].step_results.append(result)
208
+
209
+ # Calculate summary
210
+ workflow_list = list(workflows.values())
211
+ total_files = sum(w.total_steps for w in workflow_list)
212
+ total_valid = sum(w.valid_steps for w in workflow_list)
213
+ total_needs_update = sum(w.needs_update for w in workflow_list)
214
+
215
+ all_results = [r for w in workflow_list for r in w.step_results]
216
+ total_missing_required = sum(len(r.missing_required) for r in all_results)
217
+ total_missing_recommended = sum(len(r.missing_recommended) for r in all_results)
218
+
219
+ return {
220
+ "workflows": workflow_list,
221
+ "summary": {
222
+ "total_workflows": len(workflow_list),
223
+ "total_files": total_files,
224
+ "valid": total_valid,
225
+ "needs_update": total_needs_update,
226
+ "missing_required": total_missing_required,
227
+ "missing_recommended": total_missing_recommended,
228
+ },
229
+ }
@@ -0,0 +1,282 @@
1
+ """
2
+ XML schema validation for Pennyfarthing files.
3
+
4
+ Validates files against their respective schemas:
5
+ - Session files -> guides/session-schema.md
6
+ - Skill files -> guides/skill-schema.md
7
+ - Workflow step files -> guides/workflow-step-schema.md
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from dataclasses import dataclass, field
14
+ from pathlib import Path
15
+ from typing import Literal
16
+
17
+ from pennyfarthing_scripts.migration.session import (
18
+ find_session_files,
19
+ is_xml_format,
20
+ )
21
+ from pennyfarthing_scripts.migration.skill import (
22
+ RECOMMENDED_TAGS as SKILL_RECOMMENDED,
23
+ REQUIRED_TAGS as SKILL_REQUIRED,
24
+ find_skill_files,
25
+ )
26
+ from pennyfarthing_scripts.migration.step import (
27
+ RECOMMENDED_TAGS as STEP_RECOMMENDED,
28
+ REQUIRED_TAGS as STEP_REQUIRED,
29
+ STEP_META_FIELDS,
30
+ find_step_files,
31
+ )
32
+
33
+
34
+ @dataclass
35
+ class ValidationResult:
36
+ """Result of validating a single file."""
37
+
38
+ file_path: Path
39
+ file_type: Literal["session", "skill", "step"]
40
+ errors: list[str] = field(default_factory=list)
41
+ warnings: list[str] = field(default_factory=list)
42
+
43
+ @property
44
+ def is_valid(self) -> bool:
45
+ return len(self.errors) == 0
46
+
47
+ @property
48
+ def status(self) -> str:
49
+ if self.errors:
50
+ return "ERROR"
51
+ if self.warnings:
52
+ return "WARN"
53
+ return "PASS"
54
+
55
+
56
+ def _has_tag(content: str, tag: str) -> bool:
57
+ """Check if content contains a specific XML tag."""
58
+ return f"<{tag}>" in content or f"<{tag} " in content
59
+
60
+
61
+ def validate_session_file(file_path: Path) -> ValidationResult:
62
+ """Validate a session file against the schema.
63
+
64
+ Args:
65
+ file_path: Path to session file
66
+
67
+ Returns:
68
+ ValidationResult with errors/warnings
69
+ """
70
+ result = ValidationResult(file_path=file_path, file_type="session")
71
+ content = file_path.read_text()
72
+
73
+ # Check for XML format
74
+ if not is_xml_format(content):
75
+ result.errors.append("Not in XML format - needs migration")
76
+ return result
77
+
78
+ # Validate <session> root with attributes
79
+ if not re.search(r'<session\s+story="[^"]+"', content):
80
+ result.errors.append("Missing story attribute on <session>")
81
+
82
+ if not re.search(r'<session[^>]+workflow="[^"]+"', content):
83
+ result.errors.append("Missing workflow attribute on <session>")
84
+
85
+ # Validate <meta> section
86
+ if not _has_tag(content, "meta"):
87
+ result.errors.append("Missing <meta> section")
88
+ else:
89
+ if "<jira>" not in content:
90
+ result.errors.append("Missing <jira> in <meta>")
91
+ if "<started>" not in content:
92
+ result.errors.append("Missing <started> in <meta>")
93
+
94
+ # Validate <status> element
95
+ if not _has_tag(content, "status"):
96
+ result.errors.append("Missing <status> element")
97
+ else:
98
+ if 'phase="' not in content:
99
+ result.errors.append("Missing phase attribute on <status>")
100
+ if 'next-agent="' not in content:
101
+ result.warnings.append("Missing next-agent attribute on <status>")
102
+
103
+ # Validate optional sections
104
+ if not _has_tag(content, "acceptance-criteria"):
105
+ result.warnings.append("Missing <acceptance-criteria> section")
106
+
107
+ if not _has_tag(content, "work-log"):
108
+ result.warnings.append("Missing <work-log> section")
109
+
110
+ return result
111
+
112
+
113
+ def validate_skill_file(file_path: Path) -> ValidationResult:
114
+ """Validate a skill file against the schema.
115
+
116
+ Args:
117
+ file_path: Path to SKILL.md file
118
+
119
+ Returns:
120
+ ValidationResult with errors/warnings
121
+ """
122
+ skill_name = file_path.parent.name
123
+ result = ValidationResult(file_path=file_path, file_type="skill")
124
+ content = file_path.read_text()
125
+
126
+ # Check YAML frontmatter
127
+ if not content.startswith("---\n"):
128
+ result.errors.append("Missing YAML frontmatter")
129
+ else:
130
+ if "name:" not in content.split("---")[1]:
131
+ result.errors.append("Missing 'name' in frontmatter")
132
+ if "description:" not in content.split("---")[1]:
133
+ result.errors.append("Missing 'description' in frontmatter")
134
+
135
+ # Check required tags
136
+ for tag in SKILL_REQUIRED:
137
+ if not _has_tag(content, tag):
138
+ result.errors.append(f"Missing <{tag}> tag (required)")
139
+
140
+ # Check recommended tags
141
+ for tag in SKILL_RECOMMENDED:
142
+ if not _has_tag(content, tag):
143
+ result.warnings.append(f"Missing <{tag}> tag (recommended)")
144
+
145
+ return result
146
+
147
+
148
+ def validate_step_file(file_path: Path) -> ValidationResult:
149
+ """Validate a workflow step file against the schema.
150
+
151
+ Args:
152
+ file_path: Path to step-*.md file
153
+
154
+ Returns:
155
+ ValidationResult with errors/warnings
156
+ """
157
+ result = ValidationResult(file_path=file_path, file_type="step")
158
+ content = file_path.read_text()
159
+
160
+ # Determine workflow/step names from path
161
+ workflow_name = file_path.parent.parent.name
162
+ step_name = file_path.stem
163
+
164
+ # Check required tags
165
+ for tag in STEP_REQUIRED:
166
+ if not _has_tag(content, tag):
167
+ result.errors.append(f"Missing <{tag}> tag")
168
+
169
+ # Check step-meta fields if tag exists
170
+ if _has_tag(content, "step-meta"):
171
+ meta_match = re.search(r"<step-meta>(.+?)</step-meta>", content, re.DOTALL)
172
+ if meta_match:
173
+ meta_content = meta_match.group(1)
174
+ for field_name in STEP_META_FIELDS:
175
+ if f"{field_name}:" not in meta_content:
176
+ result.errors.append(f"Missing '{field_name}' in step-meta")
177
+
178
+ # Check recommended tags
179
+ for tag in STEP_RECOMMENDED:
180
+ if not _has_tag(content, tag):
181
+ result.warnings.append(f"Missing <{tag}> tag")
182
+
183
+ return result
184
+
185
+
186
+ def validate_file(file_path: Path) -> ValidationResult:
187
+ """Validate a file, auto-detecting its type.
188
+
189
+ Args:
190
+ file_path: Path to file
191
+
192
+ Returns:
193
+ ValidationResult
194
+ """
195
+ name = file_path.name
196
+
197
+ if name.endswith("-session.md"):
198
+ return validate_session_file(file_path)
199
+ elif name == "SKILL.md":
200
+ return validate_skill_file(file_path)
201
+ elif name.startswith("step-") and name.endswith(".md"):
202
+ return validate_step_file(file_path)
203
+ else:
204
+ result = ValidationResult(file_path=file_path, file_type="session")
205
+ result.errors.append(f"Unknown file type: {name}")
206
+ return result
207
+
208
+
209
+ @dataclass
210
+ class ValidationSummary:
211
+ """Summary of validation results."""
212
+
213
+ results: list[ValidationResult] = field(default_factory=list)
214
+ passed: int = 0
215
+ warnings: int = 0
216
+ errors: int = 0
217
+
218
+ def add(self, result: ValidationResult) -> None:
219
+ """Add a result to the summary."""
220
+ self.results.append(result)
221
+ if result.status == "PASS":
222
+ self.passed += 1
223
+ elif result.status == "WARN":
224
+ self.warnings += 1
225
+ else:
226
+ self.errors += 1
227
+
228
+ @property
229
+ def total(self) -> int:
230
+ return len(self.results)
231
+
232
+ @property
233
+ def success(self) -> bool:
234
+ return self.errors == 0
235
+
236
+
237
+ def validate_all(
238
+ root: Path,
239
+ *,
240
+ file_type: Literal["session", "skill", "step", "all"] = "all",
241
+ strict: bool = False,
242
+ ) -> ValidationSummary:
243
+ """Validate all files of specified type(s).
244
+
245
+ Args:
246
+ root: Project root directory
247
+ file_type: Type to validate (session, skill, step, or all)
248
+ strict: If True, treat warnings as errors
249
+
250
+ Returns:
251
+ ValidationSummary with all results
252
+ """
253
+ summary = ValidationSummary()
254
+
255
+ # Validate sessions
256
+ if file_type in ("session", "all"):
257
+ for file_path in find_session_files(root):
258
+ result = validate_session_file(file_path)
259
+ if strict and result.warnings:
260
+ result.errors.extend(result.warnings)
261
+ result.warnings = []
262
+ summary.add(result)
263
+
264
+ # Validate skills
265
+ if file_type in ("skill", "all"):
266
+ for file_path in find_skill_files(root):
267
+ result = validate_skill_file(file_path)
268
+ if strict and result.warnings:
269
+ result.errors.extend(result.warnings)
270
+ result.warnings = []
271
+ summary.add(result)
272
+
273
+ # Validate steps
274
+ if file_type in ("step", "all"):
275
+ for file_path in find_step_files(root):
276
+ result = validate_step_file(file_path)
277
+ if strict and result.warnings:
278
+ result.errors.extend(result.warnings)
279
+ result.warnings = []
280
+ summary.add(result)
281
+
282
+ return summary