@pennyfarthing/core 10.0.1 → 10.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (492) hide show
  1. package/package.json +13 -3
  2. package/pennyfarthing-dist/agents/README.md +348 -0
  3. package/pennyfarthing-dist/agents/architect.md +180 -0
  4. package/pennyfarthing-dist/agents/dev.md +169 -0
  5. package/pennyfarthing-dist/agents/devops.md +203 -0
  6. package/pennyfarthing-dist/agents/handoff.md +235 -0
  7. package/pennyfarthing-dist/agents/orchestrator.md +182 -0
  8. package/pennyfarthing-dist/agents/pm.md +152 -0
  9. package/pennyfarthing-dist/agents/reviewer-preflight.md +129 -0
  10. package/pennyfarthing-dist/agents/reviewer.md +197 -0
  11. package/pennyfarthing-dist/agents/sm-file-summary.md +79 -0
  12. package/pennyfarthing-dist/agents/sm-finish.md +82 -0
  13. package/pennyfarthing-dist/agents/sm-handoff.md +129 -0
  14. package/pennyfarthing-dist/agents/sm-setup.md +251 -0
  15. package/pennyfarthing-dist/agents/sm.md +298 -0
  16. package/pennyfarthing-dist/agents/tea.md +161 -0
  17. package/pennyfarthing-dist/agents/tech-writer.md +226 -0
  18. package/pennyfarthing-dist/agents/testing-runner.md +184 -0
  19. package/pennyfarthing-dist/agents/ux-designer.md +236 -0
  20. package/pennyfarthing-dist/agents/workflow-status-check.md +96 -0
  21. package/pennyfarthing-dist/commands/architect.md +9 -0
  22. package/pennyfarthing-dist/commands/benchmark-control.md +69 -0
  23. package/pennyfarthing-dist/commands/benchmark.md +485 -0
  24. package/pennyfarthing-dist/commands/brainstorming.md +91 -0
  25. package/pennyfarthing-dist/commands/check.md +156 -0
  26. package/pennyfarthing-dist/commands/chore.md +218 -0
  27. package/pennyfarthing-dist/commands/close-epic.md +139 -0
  28. package/pennyfarthing-dist/commands/continue-session.md +218 -0
  29. package/pennyfarthing-dist/commands/create-branches-from-story.md +358 -0
  30. package/pennyfarthing-dist/commands/create-theme.md +29 -0
  31. package/pennyfarthing-dist/commands/dev.md +9 -0
  32. package/pennyfarthing-dist/commands/devops.md +9 -0
  33. package/pennyfarthing-dist/commands/fix-blocker.md +22 -0
  34. package/pennyfarthing-dist/commands/git-cleanup.md +57 -0
  35. package/pennyfarthing-dist/commands/health-check.md +143 -0
  36. package/pennyfarthing-dist/commands/help.md +264 -0
  37. package/pennyfarthing-dist/commands/job-fair.md +102 -0
  38. package/pennyfarthing-dist/commands/list-themes.md +21 -0
  39. package/pennyfarthing-dist/commands/new-work.md +23 -0
  40. package/pennyfarthing-dist/commands/orchestrator.md +9 -0
  41. package/pennyfarthing-dist/commands/parallel-work.md +73 -0
  42. package/pennyfarthing-dist/commands/party-mode.md +77 -0
  43. package/pennyfarthing-dist/commands/patch.md +210 -0
  44. package/pennyfarthing-dist/commands/permissions.md +193 -0
  45. package/pennyfarthing-dist/commands/pm.md +9 -0
  46. package/pennyfarthing-dist/commands/prime.md +136 -0
  47. package/pennyfarthing-dist/commands/release.md +74 -0
  48. package/pennyfarthing-dist/commands/repo-status.md +49 -0
  49. package/pennyfarthing-dist/commands/retro.md +200 -0
  50. package/pennyfarthing-dist/commands/reviewer.md +9 -0
  51. package/pennyfarthing-dist/commands/run-ci.md +116 -0
  52. package/pennyfarthing-dist/commands/set-theme.md +56 -0
  53. package/pennyfarthing-dist/commands/setup.md +65 -0
  54. package/pennyfarthing-dist/commands/show-theme.md +21 -0
  55. package/pennyfarthing-dist/commands/sm.md +9 -0
  56. package/pennyfarthing-dist/commands/solo.md +447 -0
  57. package/pennyfarthing-dist/commands/sprint-planning.md +109 -0
  58. package/pennyfarthing-dist/commands/sprint.md +142 -0
  59. package/pennyfarthing-dist/commands/standalone.md +194 -0
  60. package/pennyfarthing-dist/commands/start-epic.md +168 -0
  61. package/pennyfarthing-dist/commands/sync-epic-to-jira.md +184 -0
  62. package/pennyfarthing-dist/commands/sync-work-with-sprint.md +373 -0
  63. package/pennyfarthing-dist/commands/tea.md +9 -0
  64. package/pennyfarthing-dist/commands/tech-writer.md +9 -0
  65. package/pennyfarthing-dist/commands/theme-maker.md +676 -0
  66. package/pennyfarthing-dist/commands/update-domain-docs.md +83 -0
  67. package/pennyfarthing-dist/commands/ux-designer.md +9 -0
  68. package/pennyfarthing-dist/commands/work.md +25 -0
  69. package/pennyfarthing-dist/commands/workflow.md +21 -0
  70. package/pennyfarthing-dist/guides/agent-behavior.md +92 -0
  71. package/pennyfarthing-dist/guides/agent-coordination.md +475 -0
  72. package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +432 -0
  73. package/pennyfarthing-dist/guides/agent-template-strategic.md +148 -0
  74. package/pennyfarthing-dist/guides/agent-template-tactical.md +162 -0
  75. package/pennyfarthing-dist/guides/hooks.md +230 -0
  76. package/pennyfarthing-dist/guides/measurement-framework.md +210 -0
  77. package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +766 -0
  78. package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +574 -0
  79. package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +488 -0
  80. package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +402 -0
  81. package/pennyfarthing-dist/guides/permission-protocol.md +188 -0
  82. package/pennyfarthing-dist/guides/persona-loading.md +46 -0
  83. package/pennyfarthing-dist/guides/prompt-patterns.md +338 -0
  84. package/pennyfarthing-dist/guides/scale-levels.md +114 -0
  85. package/pennyfarthing-dist/guides/session-artifacts.md +193 -0
  86. package/pennyfarthing-dist/guides/session-schema.md +346 -0
  87. package/pennyfarthing-dist/guides/skill-schema.md +412 -0
  88. package/pennyfarthing-dist/guides/workflow-schema.md +257 -0
  89. package/pennyfarthing-dist/guides/workflow-step-schema.md +512 -0
  90. package/pennyfarthing-dist/guides/worktree-mode.md +113 -0
  91. package/pennyfarthing-dist/guides/xml-tags.md +627 -0
  92. package/pennyfarthing-dist/output-styles/teaching.md +33 -0
  93. package/pennyfarthing-dist/output-styles/terse.md +20 -0
  94. package/pennyfarthing-dist/output-styles/verbose.md +28 -0
  95. package/pennyfarthing-dist/personas/themes/a-team.yaml +331 -0
  96. package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +324 -0
  97. package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +282 -0
  98. package/pennyfarthing-dist/personas/themes/blade-runner.yaml +289 -0
  99. package/pennyfarthing-dist/personas/themes/catch-22.yaml +304 -0
  100. package/pennyfarthing-dist/personas/themes/control.yaml +201 -0
  101. package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +315 -0
  102. package/pennyfarthing-dist/personas/themes/discworld.yaml +334 -0
  103. package/pennyfarthing-dist/personas/themes/doctor-who.yaml +284 -0
  104. package/pennyfarthing-dist/personas/themes/dune.yaml +301 -0
  105. package/pennyfarthing-dist/personas/themes/firefly.yaml +320 -0
  106. package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +284 -0
  107. package/pennyfarthing-dist/personas/themes/harry-potter.yaml +316 -0
  108. package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +323 -0
  109. package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +326 -0
  110. package/pennyfarthing-dist/personas/themes/mad-max.yaml +349 -0
  111. package/pennyfarthing-dist/personas/themes/mash.yaml +329 -0
  112. package/pennyfarthing-dist/personas/themes/princess-bride.yaml +344 -0
  113. package/pennyfarthing-dist/personas/themes/sandman.yaml +282 -0
  114. package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +358 -0
  115. package/pennyfarthing-dist/personas/themes/star-wars.yaml +297 -0
  116. package/pennyfarthing-dist/personas/themes/the-expanse.yaml +337 -0
  117. package/pennyfarthing-dist/personas/themes/the-matrix.yaml +342 -0
  118. package/pennyfarthing-dist/personas/themes/watchmen.yaml +285 -0
  119. package/pennyfarthing-dist/personas/themes/west-wing.yaml +285 -0
  120. package/pennyfarthing-dist/personas/themes/x-files.yaml +296 -0
  121. package/pennyfarthing-dist/scripts/README.md +87 -0
  122. package/pennyfarthing-dist/scripts/core/README.md +25 -0
  123. package/pennyfarthing-dist/scripts/core/agent-session.sh +390 -0
  124. package/pennyfarthing-dist/scripts/core/check-context.sh +194 -0
  125. package/pennyfarthing-dist/scripts/core/handoff-marker.sh +112 -0
  126. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +90 -0
  127. package/pennyfarthing-dist/scripts/core/prime.sh +30 -0
  128. package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +21 -0
  129. package/pennyfarthing-dist/scripts/git/README.md +25 -0
  130. package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +267 -0
  131. package/pennyfarthing-dist/scripts/git/git-status-all.sh +152 -0
  132. package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +79 -0
  133. package/pennyfarthing-dist/scripts/git/release.sh +246 -0
  134. package/pennyfarthing-dist/scripts/git/worktree-manager.sh +497 -0
  135. package/pennyfarthing-dist/scripts/health/drift-detection.sh +156 -0
  136. package/pennyfarthing-dist/scripts/hooks/README.md +32 -0
  137. package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
  138. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +106 -0
  139. package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +95 -0
  140. package/pennyfarthing-dist/scripts/hooks/context-warning.sh +65 -0
  141. package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +35 -0
  142. package/pennyfarthing-dist/scripts/hooks/post-merge.sh +150 -0
  143. package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +190 -0
  144. package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +71 -0
  145. package/pennyfarthing-dist/scripts/hooks/pre-push.sh +42 -0
  146. package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +20 -0
  147. package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +499 -0
  148. package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +30 -0
  149. package/pennyfarthing-dist/scripts/hooks/session-start.sh +97 -0
  150. package/pennyfarthing-dist/scripts/hooks/session-stop.sh +65 -0
  151. package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +78 -0
  152. package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +94 -0
  153. package/pennyfarthing-dist/scripts/jira/README.md +36 -0
  154. package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +95 -0
  155. package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +91 -0
  156. package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +22 -0
  157. package/pennyfarthing-dist/scripts/jira/jira-lib.sh +464 -0
  158. package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +260 -0
  159. package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +18 -0
  160. package/pennyfarthing-dist/scripts/jira/jira-sync.sh +16 -0
  161. package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +16 -0
  162. package/pennyfarthing-dist/scripts/jira/sync-epic-to-jira.sh +16 -0
  163. package/pennyfarthing-dist/scripts/lib/README.md +29 -0
  164. package/pennyfarthing-dist/scripts/lib/background-tasks.sh +177 -0
  165. package/pennyfarthing-dist/scripts/lib/checkpoint.sh +136 -0
  166. package/pennyfarthing-dist/scripts/lib/common.sh +212 -0
  167. package/pennyfarthing-dist/scripts/lib/file-lock.sh +269 -0
  168. package/pennyfarthing-dist/scripts/lib/find-root.sh +58 -0
  169. package/pennyfarthing-dist/scripts/lib/logging.sh +186 -0
  170. package/pennyfarthing-dist/scripts/lib/retry.sh +76 -0
  171. package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +102 -0
  172. package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +91 -0
  173. package/pennyfarthing-dist/scripts/misc/README.md +44 -0
  174. package/pennyfarthing-dist/scripts/misc/add-short-names.sh +13 -0
  175. package/pennyfarthing-dist/scripts/misc/add_short_names.py +226 -0
  176. package/pennyfarthing-dist/scripts/misc/backlog.sh +77 -0
  177. package/pennyfarthing-dist/scripts/misc/check-status.sh +247 -0
  178. package/pennyfarthing-dist/scripts/misc/find-related-work.sh +231 -0
  179. package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +107 -0
  180. package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +74 -0
  181. package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +10 -0
  182. package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +319 -0
  183. package/pennyfarthing-dist/scripts/misc/repo-scan.sh +141 -0
  184. package/pennyfarthing-dist/scripts/misc/repo-utils.sh +778 -0
  185. package/pennyfarthing-dist/scripts/misc/run-ci.sh +212 -0
  186. package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +7 -0
  187. package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +319 -0
  188. package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +193 -0
  189. package/pennyfarthing-dist/scripts/misc/statusline.sh +257 -0
  190. package/pennyfarthing-dist/scripts/misc/uninstall.sh +275 -0
  191. package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +160 -0
  192. package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +417 -0
  193. package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +54 -0
  194. package/pennyfarthing-dist/scripts/sprint/README.md +29 -0
  195. package/pennyfarthing-dist/scripts/sprint/archive-story.sh +133 -0
  196. package/pennyfarthing-dist/scripts/sprint/available-stories.sh +91 -0
  197. package/pennyfarthing-dist/scripts/sprint/check-story.sh +158 -0
  198. package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +52 -0
  199. package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +63 -0
  200. package/pennyfarthing-dist/scripts/sprint/list-future.sh +145 -0
  201. package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +110 -0
  202. package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +148 -0
  203. package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +415 -0
  204. package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +33 -0
  205. package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +230 -0
  206. package/pennyfarthing-dist/scripts/sprint/sprint-status.sh +134 -0
  207. package/pennyfarthing-dist/scripts/sprint/validate-sprint-yaml.sh +139 -0
  208. package/pennyfarthing-dist/scripts/story/README.md +23 -0
  209. package/pennyfarthing-dist/scripts/story/create-story.sh +19 -0
  210. package/pennyfarthing-dist/scripts/story/size-story.sh +18 -0
  211. package/pennyfarthing-dist/scripts/story/story-template.sh +18 -0
  212. package/pennyfarthing-dist/scripts/test/README.md +23 -0
  213. package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +59 -0
  214. package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +220 -0
  215. package/pennyfarthing-dist/scripts/test/swebench-judge.py +374 -0
  216. package/pennyfarthing-dist/scripts/test/test-cache.sh +165 -0
  217. package/pennyfarthing-dist/scripts/test/test-setup.sh +337 -0
  218. package/pennyfarthing-dist/scripts/tests/check.test.sh +582 -0
  219. package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +515 -0
  220. package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +599 -0
  221. package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +332 -0
  222. package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +573 -0
  223. package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +859 -0
  224. package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +662 -0
  225. package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +589 -0
  226. package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +106 -0
  227. package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +597 -0
  228. package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +514 -0
  229. package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +517 -0
  230. package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +331 -0
  231. package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +647 -0
  232. package/pennyfarthing-dist/scripts/theme/README.md +22 -0
  233. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +13 -0
  234. package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +402 -0
  235. package/pennyfarthing-dist/scripts/theme/list-themes.sh +30 -0
  236. package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +97 -0
  237. package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +576 -0
  238. package/pennyfarthing-dist/scripts/workflow/README.md +28 -0
  239. package/pennyfarthing-dist/scripts/workflow/check.py +502 -0
  240. package/pennyfarthing-dist/scripts/workflow/check.sh +24 -0
  241. package/pennyfarthing-dist/scripts/workflow/complete-step.py +304 -0
  242. package/pennyfarthing-dist/scripts/workflow/finish-story.sh +154 -0
  243. package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +222 -0
  244. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +61 -0
  245. package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +13 -0
  246. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +124 -0
  247. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +34 -0
  248. package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +157 -0
  249. package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +132 -0
  250. package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +250 -0
  251. package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +161 -0
  252. package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +246 -0
  253. package/pennyfarthing-dist/skills/changelog/SKILL.md +385 -0
  254. package/pennyfarthing-dist/skills/code-review/SKILL.md +172 -0
  255. package/pennyfarthing-dist/skills/context-engineering/SKILL.md +277 -0
  256. package/pennyfarthing-dist/skills/cyclist/SKILL.md +88 -0
  257. package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +461 -0
  258. package/pennyfarthing-dist/skills/finalize-run/SKILL.md +261 -0
  259. package/pennyfarthing-dist/skills/jira/SKILL.md +508 -0
  260. package/pennyfarthing-dist/skills/judge/SKILL.md +644 -0
  261. package/pennyfarthing-dist/skills/just/SKILL.md +414 -0
  262. package/pennyfarthing-dist/skills/mermaid/SKILL.md +256 -0
  263. package/pennyfarthing-dist/skills/otel/skill.md +227 -0
  264. package/pennyfarthing-dist/skills/permissions/skill.md +157 -0
  265. package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +187 -0
  266. package/pennyfarthing-dist/skills/skill-registry.schema.json +107 -0
  267. package/pennyfarthing-dist/skills/skill-registry.yaml +393 -0
  268. package/pennyfarthing-dist/skills/sprint/scripts/archive-story.sh +101 -0
  269. package/pennyfarthing-dist/skills/sprint/scripts/available-stories.sh +97 -0
  270. package/pennyfarthing-dist/skills/sprint/scripts/check-story.sh +164 -0
  271. package/pennyfarthing-dist/skills/sprint/scripts/create-jira-epic.sh +101 -0
  272. package/pennyfarthing-dist/skills/sprint/scripts/new-sprint.sh +116 -0
  273. package/pennyfarthing-dist/skills/sprint/scripts/promote-epic.sh +164 -0
  274. package/pennyfarthing-dist/skills/sprint/scripts/sprint-info.sh +39 -0
  275. package/pennyfarthing-dist/skills/sprint/scripts/sprint-status.sh +147 -0
  276. package/pennyfarthing-dist/skills/sprint/scripts/sync-epic-jira.sh +93 -0
  277. package/pennyfarthing-dist/skills/sprint/skill.md +465 -0
  278. package/pennyfarthing-dist/skills/story/scripts/create-story.sh +159 -0
  279. package/pennyfarthing-dist/skills/story/scripts/size-story.sh +198 -0
  280. package/pennyfarthing-dist/skills/story/scripts/story-template.sh +162 -0
  281. package/pennyfarthing-dist/skills/story/skill.md +219 -0
  282. package/pennyfarthing-dist/skills/systematic-debugging/SKILL.md +446 -0
  283. package/pennyfarthing-dist/skills/testing/SKILL.md +121 -0
  284. package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +124 -0
  285. package/pennyfarthing-dist/skills/theme/skill.md +141 -0
  286. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +178 -0
  287. package/pennyfarthing-dist/skills/workflow/scripts/list-workflows.sh +91 -0
  288. package/pennyfarthing-dist/skills/workflow/scripts/resume-workflow.sh +163 -0
  289. package/pennyfarthing-dist/skills/workflow/scripts/show-workflow.sh +138 -0
  290. package/pennyfarthing-dist/skills/workflow/scripts/start-workflow.sh +273 -0
  291. package/pennyfarthing-dist/skills/workflow/scripts/workflow-status.sh +167 -0
  292. package/pennyfarthing-dist/skills/workflow/skill.md +345 -0
  293. package/pennyfarthing-dist/skills/yq/SKILL.md +272 -0
  294. package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +187 -0
  295. package/pennyfarthing-dist/templates/LEADERBOARD.template.md +59 -0
  296. package/pennyfarthing-dist/templates/agent-scopes.yaml.template +276 -0
  297. package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +61 -0
  298. package/pennyfarthing-dist/templates/persona-config.yaml.template +22 -0
  299. package/pennyfarthing-dist/templates/preferences.yaml.template +15 -0
  300. package/pennyfarthing-dist/templates/settings.local.json.template +130 -0
  301. package/pennyfarthing-dist/templates/setup-env.sh.template +18 -0
  302. package/pennyfarthing-dist/templates/shared-context.md.template +70 -0
  303. package/pennyfarthing-dist/templates/sidecar/decisions.md.template +40 -0
  304. package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +37 -0
  305. package/pennyfarthing-dist/templates/sidecar/patterns.md.template +34 -0
  306. package/pennyfarthing-dist/workflows/agent-docs.yaml +70 -0
  307. package/pennyfarthing-dist/workflows/architecture/steps/step-01-initialize.md +113 -0
  308. package/pennyfarthing-dist/workflows/architecture/steps/step-01b-continue.md +105 -0
  309. package/pennyfarthing-dist/workflows/architecture/steps/step-02-context.md +127 -0
  310. package/pennyfarthing-dist/workflows/architecture/steps/step-03-patterns.md +145 -0
  311. package/pennyfarthing-dist/workflows/architecture/steps/step-04-components.md +150 -0
  312. package/pennyfarthing-dist/workflows/architecture/steps/step-05-interfaces.md +145 -0
  313. package/pennyfarthing-dist/workflows/architecture/steps/step-06-risks.md +154 -0
  314. package/pennyfarthing-dist/workflows/architecture/steps/step-07-document.md +172 -0
  315. package/pennyfarthing-dist/workflows/architecture/templates/architecture-decision.md +102 -0
  316. package/pennyfarthing-dist/workflows/architecture.yaml +65 -0
  317. package/pennyfarthing-dist/workflows/bdd.yaml +60 -0
  318. package/pennyfarthing-dist/workflows/brainstorming/brain-methods.csv +62 -0
  319. package/pennyfarthing-dist/workflows/brainstorming/checklist.md +44 -0
  320. package/pennyfarthing-dist/workflows/brainstorming/instructions.md +736 -0
  321. package/pennyfarthing-dist/workflows/brainstorming/workflow.yaml +49 -0
  322. package/pennyfarthing-dist/workflows/code-review/checklist.md +23 -0
  323. package/pennyfarthing-dist/workflows/code-review/instructions.md +234 -0
  324. package/pennyfarthing-dist/workflows/code-review/workflow.yaml +51 -0
  325. package/pennyfarthing-dist/workflows/dev-story/checklist.md +80 -0
  326. package/pennyfarthing-dist/workflows/dev-story/instructions.xml +410 -0
  327. package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +50 -0
  328. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-01-validate-prerequisites.md +281 -0
  329. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-02-design-epics.md +256 -0
  330. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-03-create-stories.md +298 -0
  331. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +177 -0
  332. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +145 -0
  333. package/pennyfarthing-dist/workflows/epics-and-stories/templates/epics-template.md +57 -0
  334. package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +28 -0
  335. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +103 -0
  336. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-02-categorize.md +147 -0
  337. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +215 -0
  338. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +97 -0
  339. package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +78 -0
  340. package/pennyfarthing-dist/workflows/git-cleanup.yaml +59 -0
  341. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-01-document-discovery.md +211 -0
  342. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-02-prd-analysis.md +199 -0
  343. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-03-epic-coverage-validation.md +202 -0
  344. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-04-ux-alignment.md +162 -0
  345. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-05-epic-quality-review.md +280 -0
  346. package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-06-final-assessment.md +158 -0
  347. package/pennyfarthing-dist/workflows/implementation-readiness/templates/readiness-report-template.md +4 -0
  348. package/pennyfarthing-dist/workflows/implementation-readiness/workflow.yaml +40 -0
  349. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-01-connect.md +257 -0
  350. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-02-explore.md +107 -0
  351. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-03-fix.md +127 -0
  352. package/pennyfarthing-dist/workflows/interactive-debug/steps/step-04-commit.md +122 -0
  353. package/pennyfarthing-dist/workflows/interactive-debug/workflow.yaml +51 -0
  354. package/pennyfarthing-dist/workflows/patch.yaml +67 -0
  355. package/pennyfarthing-dist/workflows/prd/data/domain-complexity.csv +13 -0
  356. package/pennyfarthing-dist/workflows/prd/data/prd-purpose.md +197 -0
  357. package/pennyfarthing-dist/workflows/prd/data/project-types.csv +11 -0
  358. package/pennyfarthing-dist/workflows/prd/steps-c/step-01-init.md +197 -0
  359. package/pennyfarthing-dist/workflows/prd/steps-c/step-01b-continue.md +159 -0
  360. package/pennyfarthing-dist/workflows/prd/steps-c/step-02-discovery.md +230 -0
  361. package/pennyfarthing-dist/workflows/prd/steps-c/step-03-success.md +232 -0
  362. package/pennyfarthing-dist/workflows/prd/steps-c/step-04-journeys.md +219 -0
  363. package/pennyfarthing-dist/workflows/prd/steps-c/step-05-domain.md +213 -0
  364. package/pennyfarthing-dist/workflows/prd/steps-c/step-06-innovation.md +232 -0
  365. package/pennyfarthing-dist/workflows/prd/steps-c/step-07-project-type.md +243 -0
  366. package/pennyfarthing-dist/workflows/prd/steps-c/step-08-scoping.md +234 -0
  367. package/pennyfarthing-dist/workflows/prd/steps-c/step-09-functional.md +237 -0
  368. package/pennyfarthing-dist/workflows/prd/steps-c/step-10-nonfunctional.md +248 -0
  369. package/pennyfarthing-dist/workflows/prd/steps-c/step-11-polish.md +223 -0
  370. package/pennyfarthing-dist/workflows/prd/steps-c/step-12-complete.md +186 -0
  371. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01-discovery.md +253 -0
  372. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01b-legacy-conversion.md +214 -0
  373. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-02-review.md +255 -0
  374. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-03-edit.md +259 -0
  375. package/pennyfarthing-dist/workflows/prd/steps-e/step-e-04-complete.md +174 -0
  376. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-01-discovery.md +224 -0
  377. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02-format-detection.md +197 -0
  378. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02b-parity-check.md +215 -0
  379. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-03-density-validation.md +180 -0
  380. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +220 -0
  381. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-05-measurability-validation.md +234 -0
  382. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-06-traceability-validation.md +223 -0
  383. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +211 -0
  384. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +249 -0
  385. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-09-project-type-validation.md +269 -0
  386. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-10-smart-validation.md +215 -0
  387. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +270 -0
  388. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-12-completeness-validation.md +248 -0
  389. package/pennyfarthing-dist/workflows/prd/steps-v/step-v-13-report-complete.md +238 -0
  390. package/pennyfarthing-dist/workflows/prd/templates/prd-template.md +10 -0
  391. package/pennyfarthing-dist/workflows/prd/workflow.yaml +42 -0
  392. package/pennyfarthing-dist/workflows/product-brief/steps/step-01-init.md +195 -0
  393. package/pennyfarthing-dist/workflows/product-brief/steps/step-01b-continue.md +180 -0
  394. package/pennyfarthing-dist/workflows/product-brief/steps/step-02-vision.md +221 -0
  395. package/pennyfarthing-dist/workflows/product-brief/steps/step-03-users.md +224 -0
  396. package/pennyfarthing-dist/workflows/product-brief/steps/step-04-metrics.md +228 -0
  397. package/pennyfarthing-dist/workflows/product-brief/steps/step-05-scope.md +243 -0
  398. package/pennyfarthing-dist/workflows/product-brief/steps/step-06-complete.md +216 -0
  399. package/pennyfarthing-dist/workflows/product-brief/templates/product-brief.template.md +10 -0
  400. package/pennyfarthing-dist/workflows/product-brief/workflow.yaml +31 -0
  401. package/pennyfarthing-dist/workflows/project-context/project-context-template.md +21 -0
  402. package/pennyfarthing-dist/workflows/project-context/steps/step-01-discover.md +206 -0
  403. package/pennyfarthing-dist/workflows/project-context/steps/step-02-generate.md +349 -0
  404. package/pennyfarthing-dist/workflows/project-context/steps/step-03-complete.md +306 -0
  405. package/pennyfarthing-dist/workflows/project-context/workflow.yaml +27 -0
  406. package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +157 -0
  407. package/pennyfarthing-dist/workflows/project-setup/steps/step-02-clone-repos.md +217 -0
  408. package/pennyfarthing-dist/workflows/project-setup/steps/step-03-repos-yaml.md +159 -0
  409. package/pennyfarthing-dist/workflows/project-setup/steps/step-04-claude-md.md +186 -0
  410. package/pennyfarthing-dist/workflows/project-setup/steps/step-05-shared-context.md +185 -0
  411. package/pennyfarthing-dist/workflows/project-setup/steps/step-06-task-runner.md +279 -0
  412. package/pennyfarthing-dist/workflows/project-setup/steps/step-07-theme.md +200 -0
  413. package/pennyfarthing-dist/workflows/project-setup/steps/step-08-theme-packs.md +142 -0
  414. package/pennyfarthing-dist/workflows/project-setup/steps/step-09-cyclist.md +245 -0
  415. package/pennyfarthing-dist/workflows/project-setup/steps/step-10-complete.md +204 -0
  416. package/pennyfarthing-dist/workflows/project-setup/workflow.yaml +41 -0
  417. package/pennyfarthing-dist/workflows/quick-dev/steps/step-01-mode-detection.md +177 -0
  418. package/pennyfarthing-dist/workflows/quick-dev/steps/step-02-context-gathering.md +143 -0
  419. package/pennyfarthing-dist/workflows/quick-dev/steps/step-03-execute.md +138 -0
  420. package/pennyfarthing-dist/workflows/quick-dev/steps/step-04-self-check.md +135 -0
  421. package/pennyfarthing-dist/workflows/quick-dev/steps/step-05-adversarial-review.md +129 -0
  422. package/pennyfarthing-dist/workflows/quick-dev/steps/step-06-resolve-findings.md +163 -0
  423. package/pennyfarthing-dist/workflows/quick-dev/workflow.yaml +27 -0
  424. package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +201 -0
  425. package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +156 -0
  426. package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +140 -0
  427. package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +203 -0
  428. package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +74 -0
  429. package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +27 -0
  430. package/pennyfarthing-dist/workflows/release/steps/step-01-preflight.md +105 -0
  431. package/pennyfarthing-dist/workflows/release/steps/step-02-bump.md +95 -0
  432. package/pennyfarthing-dist/workflows/release/steps/step-03-changelog.md +125 -0
  433. package/pennyfarthing-dist/workflows/release/steps/step-04-readme.md +101 -0
  434. package/pennyfarthing-dist/workflows/release/steps/step-05-claude-md.md +102 -0
  435. package/pennyfarthing-dist/workflows/release/steps/step-06-retro.md +59 -0
  436. package/pennyfarthing-dist/workflows/release/steps/step-07-commit.md +109 -0
  437. package/pennyfarthing-dist/workflows/release/steps/step-08-merge.md +65 -0
  438. package/pennyfarthing-dist/workflows/release/steps/step-09-push.md +75 -0
  439. package/pennyfarthing-dist/workflows/release/steps/step-10-publish.md +93 -0
  440. package/pennyfarthing-dist/workflows/release/steps/step-11-finalize.md +71 -0
  441. package/pennyfarthing-dist/workflows/release.yaml +62 -0
  442. package/pennyfarthing-dist/workflows/research/steps-domain/step-01-init.md +159 -0
  443. package/pennyfarthing-dist/workflows/research/steps-domain/step-02-domain-analysis.md +253 -0
  444. package/pennyfarthing-dist/workflows/research/steps-domain/step-03-competitive-landscape.md +263 -0
  445. package/pennyfarthing-dist/workflows/research/steps-domain/step-04-regulatory-focus.md +232 -0
  446. package/pennyfarthing-dist/workflows/research/steps-domain/step-05-technical-trends.md +260 -0
  447. package/pennyfarthing-dist/workflows/research/steps-domain/step-06-research-synthesis.md +477 -0
  448. package/pennyfarthing-dist/workflows/research/steps-market/step-01-init.md +205 -0
  449. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-behavior.md +262 -0
  450. package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-insights.md +227 -0
  451. package/pennyfarthing-dist/workflows/research/steps-market/step-03-customer-pain-points.md +275 -0
  452. package/pennyfarthing-dist/workflows/research/steps-market/step-04-customer-decisions.md +286 -0
  453. package/pennyfarthing-dist/workflows/research/steps-market/step-05-competitive-analysis.md +203 -0
  454. package/pennyfarthing-dist/workflows/research/steps-market/step-06-research-completion.md +510 -0
  455. package/pennyfarthing-dist/workflows/research/steps-technical/step-01-init.md +159 -0
  456. package/pennyfarthing-dist/workflows/research/steps-technical/step-02-technical-overview.md +264 -0
  457. package/pennyfarthing-dist/workflows/research/steps-technical/step-03-integration-patterns.md +274 -0
  458. package/pennyfarthing-dist/workflows/research/steps-technical/step-04-architectural-patterns.md +228 -0
  459. package/pennyfarthing-dist/workflows/research/steps-technical/step-05-implementation-research.md +267 -0
  460. package/pennyfarthing-dist/workflows/research/steps-technical/step-06-research-synthesis.md +522 -0
  461. package/pennyfarthing-dist/workflows/research/templates/research.template.md +29 -0
  462. package/pennyfarthing-dist/workflows/research/workflow.yaml +45 -0
  463. package/pennyfarthing-dist/workflows/retrospective/checklist.md +31 -0
  464. package/pennyfarthing-dist/workflows/retrospective/instructions.md +1443 -0
  465. package/pennyfarthing-dist/workflows/retrospective/workflow.yaml +50 -0
  466. package/pennyfarthing-dist/workflows/sprint-planning/checklist.md +33 -0
  467. package/pennyfarthing-dist/workflows/sprint-planning/sprint-status-template.yaml +55 -0
  468. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-01-parse-epic-files.md +69 -0
  469. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-02-build-sprint-status.md +61 -0
  470. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-03-status-detection.md +80 -0
  471. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-04-generate-status-file.md +90 -0
  472. package/pennyfarthing-dist/workflows/sprint-planning/steps/step-05-validate-and-report.md +78 -0
  473. package/pennyfarthing-dist/workflows/sprint-planning/workflow.yaml +34 -0
  474. package/pennyfarthing-dist/workflows/tdd.yaml +50 -0
  475. package/pennyfarthing-dist/workflows/trivial.yaml +40 -0
  476. package/pennyfarthing-dist/workflows/ux-design/steps/step-01-init.md +141 -0
  477. package/pennyfarthing-dist/workflows/ux-design/steps/step-01b-continue.md +133 -0
  478. package/pennyfarthing-dist/workflows/ux-design/steps/step-02-discovery.md +196 -0
  479. package/pennyfarthing-dist/workflows/ux-design/steps/step-03-core-experience.md +222 -0
  480. package/pennyfarthing-dist/workflows/ux-design/steps/step-04-emotional-response.md +225 -0
  481. package/pennyfarthing-dist/workflows/ux-design/steps/step-05-inspiration.md +240 -0
  482. package/pennyfarthing-dist/workflows/ux-design/steps/step-06-design-system.md +258 -0
  483. package/pennyfarthing-dist/workflows/ux-design/steps/step-07-defining-experience.md +260 -0
  484. package/pennyfarthing-dist/workflows/ux-design/steps/step-08-visual-foundation.md +230 -0
  485. package/pennyfarthing-dist/workflows/ux-design/steps/step-09-design-directions.md +230 -0
  486. package/pennyfarthing-dist/workflows/ux-design/steps/step-10-user-journeys.md +247 -0
  487. package/pennyfarthing-dist/workflows/ux-design/steps/step-11-component-strategy.md +254 -0
  488. package/pennyfarthing-dist/workflows/ux-design/steps/step-12-ux-patterns.md +243 -0
  489. package/pennyfarthing-dist/workflows/ux-design/steps/step-13-responsive-accessibility.md +270 -0
  490. package/pennyfarthing-dist/workflows/ux-design/steps/step-14-complete.md +234 -0
  491. package/pennyfarthing-dist/workflows/ux-design/ux-design-template.md +13 -0
  492. package/pennyfarthing-dist/workflows/ux-design/workflow.yaml +41 -0
@@ -0,0 +1,502 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ check.py - Quality gate runner for pre-handoff verification
4
+
5
+ Story 21-1: /check command with dev-handoff integration
6
+
7
+ Usage: python check.py [OPTIONS]
8
+
9
+ Options:
10
+ --skip-check Skip all checks (emergency bypass)
11
+ --tests-only Run only tests, skip lint and typecheck
12
+ --filter PATTERN Filter tests by pattern (passed to test runner)
13
+ --repo REPO Run checks in specific repo subdirectory
14
+ --no-lint Skip lint check
15
+ --no-typecheck Skip type check
16
+ --fast Skip slow packages (cyclist/Electron) for rapid iteration
17
+
18
+ Runs lint, type check, and tests concurrently. Reports pass/fail status.
19
+ Returns exit code 0 on all passing, non-zero on any failure.
20
+ """
21
+
22
+ import argparse
23
+ import asyncio
24
+ import json
25
+ import os
26
+ import shutil
27
+ import sys
28
+ from dataclasses import dataclass, field
29
+ from enum import Enum
30
+ from pathlib import Path
31
+ from typing import Optional
32
+
33
+
34
+ class CheckStatus(Enum):
35
+ PASS = "pass"
36
+ FAIL = "fail"
37
+ SKIP = "skip"
38
+
39
+
40
+ @dataclass
41
+ class CheckResult:
42
+ name: str
43
+ status: CheckStatus
44
+ command: Optional[str] = None
45
+ message: Optional[str] = None
46
+
47
+
48
+ @dataclass
49
+ class CheckStats:
50
+ run: int = 0
51
+ passed: int = 0
52
+ failed: int = 0
53
+ skipped: int = 0
54
+
55
+ def record(self, status: CheckStatus) -> None:
56
+ if status == CheckStatus.PASS:
57
+ self.run += 1
58
+ self.passed += 1
59
+ elif status == CheckStatus.FAIL:
60
+ self.run += 1
61
+ self.failed += 1
62
+ elif status == CheckStatus.SKIP:
63
+ self.skipped += 1
64
+
65
+
66
+ @dataclass
67
+ class RepoConfig:
68
+ path: str = ""
69
+ lint_cmd: str = ""
70
+ test_cmd: str = ""
71
+ test_filter_flag: str = ""
72
+ language: str = ""
73
+
74
+
75
+ @dataclass
76
+ class CheckContext:
77
+ project_root: Path
78
+ working_dir: Path
79
+ target_repo: str = ""
80
+ test_filter: str = ""
81
+ no_lint: bool = False
82
+ no_typecheck: bool = False
83
+ fast_mode: bool = False
84
+ repo_config: RepoConfig = field(default_factory=RepoConfig)
85
+ stats: CheckStats = field(default_factory=CheckStats)
86
+
87
+
88
+ # ANSI colors
89
+ class Colors:
90
+ def __init__(self, enabled: bool = True):
91
+ if enabled and sys.stdout.isatty():
92
+ self.RED = "\033[0;31m"
93
+ self.GREEN = "\033[0;32m"
94
+ self.YELLOW = "\033[0;33m"
95
+ self.CYAN = "\033[0;36m"
96
+ self.NC = "\033[0m"
97
+ else:
98
+ self.RED = ""
99
+ self.GREEN = ""
100
+ self.YELLOW = ""
101
+ self.CYAN = ""
102
+ self.NC = ""
103
+
104
+
105
+ COLORS = Colors()
106
+
107
+
108
+ def print_pass(name: str, command: Optional[str] = None) -> None:
109
+ suffix = f" ({command})" if command else ""
110
+ print(f" {COLORS.GREEN}[PASS]{COLORS.NC} {name}{suffix}")
111
+
112
+
113
+ def print_fail(name: str, command: Optional[str] = None) -> None:
114
+ suffix = f" ({command})" if command else ""
115
+ print(f" {COLORS.RED}[FAIL]{COLORS.NC} {name}{suffix}")
116
+
117
+
118
+ def print_skip(name: str, reason: str = "") -> None:
119
+ suffix = f" - {reason}" if reason else ""
120
+ print(f" {COLORS.YELLOW}[SKIP]{COLORS.NC} {name}{suffix}")
121
+
122
+
123
+ def print_section(title: str) -> None:
124
+ print()
125
+ print(f"{COLORS.CYAN}{title}{COLORS.NC}")
126
+ print("=" * 40)
127
+
128
+
129
+ def find_project_root() -> Path:
130
+ """Find project root by looking for .pennyfarthing directory."""
131
+ current = Path.cwd()
132
+ while current != current.parent:
133
+ if (current / ".pennyfarthing").is_dir():
134
+ return current
135
+ current = current.parent
136
+ return Path.cwd()
137
+
138
+
139
+ def detect_project_type(working_dir: Path) -> str:
140
+ """Detect project type based on files present."""
141
+ if (working_dir / "package.json").exists():
142
+ return "node"
143
+
144
+ # Check for Go files
145
+ go_files = list(working_dir.glob("*.go"))
146
+ if go_files:
147
+ return "go"
148
+
149
+ if (working_dir / "go.mod").exists():
150
+ return "go"
151
+
152
+ return "unknown"
153
+
154
+
155
+ def has_just_recipe(recipe: str, working_dir: Path) -> bool:
156
+ """Check if justfile has a specific recipe."""
157
+ if not (working_dir / "justfile").exists():
158
+ return False
159
+ if not shutil.which("just"):
160
+ return False
161
+
162
+ try:
163
+ import subprocess
164
+ result = subprocess.run(
165
+ ["just", "--list"],
166
+ cwd=working_dir,
167
+ capture_output=True,
168
+ text=True,
169
+ timeout=5
170
+ )
171
+ return any(line.startswith(f"{recipe} ") or line.strip() == recipe
172
+ for line in result.stdout.splitlines())
173
+ except Exception:
174
+ return False
175
+
176
+
177
+ def has_npm_script(script: str, working_dir: Path) -> bool:
178
+ """Check if package.json has a specific script."""
179
+ package_json = working_dir / "package.json"
180
+ if not package_json.exists():
181
+ return False
182
+
183
+ try:
184
+ with open(package_json) as f:
185
+ data = json.load(f)
186
+ return script in data.get("scripts", {})
187
+ except Exception:
188
+ return False
189
+
190
+
191
+ async def run_command(cmd: list[str], cwd: Path) -> tuple[bool, str]:
192
+ """Run a command asynchronously and return (success, output)."""
193
+ try:
194
+ proc = await asyncio.create_subprocess_exec(
195
+ *cmd,
196
+ cwd=cwd,
197
+ stdout=asyncio.subprocess.PIPE,
198
+ stderr=asyncio.subprocess.PIPE
199
+ )
200
+ stdout, stderr = await proc.communicate()
201
+ success = proc.returncode == 0
202
+ output = stdout.decode() + stderr.decode()
203
+ return success, output
204
+ except Exception as e:
205
+ return False, str(e)
206
+
207
+
208
+ async def run_shell_command(cmd: str, cwd: Path) -> tuple[bool, str]:
209
+ """Run a shell command asynchronously."""
210
+ try:
211
+ proc = await asyncio.create_subprocess_shell(
212
+ cmd,
213
+ cwd=cwd,
214
+ stdout=asyncio.subprocess.PIPE,
215
+ stderr=asyncio.subprocess.PIPE
216
+ )
217
+ stdout, stderr = await proc.communicate()
218
+ success = proc.returncode == 0
219
+ output = stdout.decode() + stderr.decode()
220
+ return success, output
221
+ except Exception as e:
222
+ return False, str(e)
223
+
224
+
225
+ async def run_lint(ctx: CheckContext) -> CheckResult:
226
+ """Run lint check."""
227
+ if ctx.no_lint:
228
+ return CheckResult("Lint", CheckStatus.SKIP, message="skipped by --no-lint or --tests-only")
229
+
230
+ working_dir = ctx.working_dir
231
+
232
+ # Use repo config lint command if available
233
+ if ctx.repo_config.lint_cmd:
234
+ success, _ = await run_shell_command(ctx.repo_config.lint_cmd, working_dir)
235
+ return CheckResult(
236
+ "Lint",
237
+ CheckStatus.PASS if success else CheckStatus.FAIL,
238
+ command=ctx.repo_config.lint_cmd
239
+ )
240
+
241
+ # Prefer justfile recipes
242
+ if has_just_recipe("lint", working_dir):
243
+ success, _ = await run_command(["just", "lint"], working_dir)
244
+ return CheckResult("Lint", CheckStatus.PASS if success else CheckStatus.FAIL, command="just lint")
245
+
246
+ project_type = detect_project_type(working_dir)
247
+
248
+ if project_type == "node" and has_npm_script("lint", working_dir):
249
+ success, _ = await run_command(["npm", "run", "lint"], working_dir)
250
+ return CheckResult("Lint", CheckStatus.PASS if success else CheckStatus.FAIL, command="npm run lint")
251
+
252
+ if project_type == "go" and shutil.which("golangci-lint"):
253
+ success, _ = await run_command(["golangci-lint", "run"], working_dir)
254
+ return CheckResult("Lint", CheckStatus.PASS if success else CheckStatus.FAIL, command="golangci-lint")
255
+
256
+ eslint_path = working_dir / "node_modules" / ".bin" / "eslint"
257
+ if eslint_path.exists():
258
+ success, _ = await run_command([str(eslint_path), "."], working_dir)
259
+ return CheckResult("Lint", CheckStatus.PASS if success else CheckStatus.FAIL, command="eslint")
260
+
261
+ return CheckResult("Lint", CheckStatus.SKIP, message="no lint command configured")
262
+
263
+
264
+ async def run_typecheck(ctx: CheckContext) -> CheckResult:
265
+ """Run type check."""
266
+ if ctx.no_typecheck:
267
+ return CheckResult("Type Check", CheckStatus.SKIP, message="skipped by --no-typecheck or --tests-only")
268
+
269
+ working_dir = ctx.working_dir
270
+
271
+ # Prefer justfile recipes
272
+ if has_just_recipe("typecheck", working_dir):
273
+ success, _ = await run_command(["just", "typecheck"], working_dir)
274
+ return CheckResult("Type Check", CheckStatus.PASS if success else CheckStatus.FAIL, command="just typecheck")
275
+
276
+ has_tsconfig = (working_dir / "tsconfig.json").exists()
277
+
278
+ if has_tsconfig and has_npm_script("typecheck", working_dir):
279
+ success, _ = await run_command(["npm", "run", "typecheck"], working_dir)
280
+ return CheckResult("Type Check", CheckStatus.PASS if success else CheckStatus.FAIL, command="npm run typecheck")
281
+
282
+ if has_tsconfig and shutil.which("tsc"):
283
+ success, _ = await run_command(["tsc", "--noEmit"], working_dir)
284
+ return CheckResult("Type Check", CheckStatus.PASS if success else CheckStatus.FAIL, command="tsc --noEmit")
285
+
286
+ tsc_path = working_dir / "node_modules" / ".bin" / "tsc"
287
+ if has_tsconfig and tsc_path.exists():
288
+ success, _ = await run_command([str(tsc_path), "--noEmit"], working_dir)
289
+ return CheckResult("Type Check", CheckStatus.PASS if success else CheckStatus.FAIL, command="tsc --noEmit")
290
+
291
+ if has_tsconfig:
292
+ return CheckResult("Type Check", CheckStatus.SKIP, message="TypeScript found but no typecheck command")
293
+
294
+ return CheckResult("Type Check", CheckStatus.SKIP, message="not a TypeScript project")
295
+
296
+
297
+ async def run_tests(ctx: CheckContext) -> CheckResult:
298
+ """Run tests."""
299
+ working_dir = ctx.working_dir
300
+ test_filter = ctx.test_filter
301
+
302
+ if test_filter:
303
+ print(f" Filter: {test_filter}")
304
+
305
+ # Use repo config test command if available
306
+ if ctx.repo_config.test_cmd:
307
+ cmd = ctx.repo_config.test_cmd
308
+ if test_filter and ctx.repo_config.test_filter_flag:
309
+ cmd = f'{cmd} {ctx.repo_config.test_filter_flag} "{test_filter}"'
310
+ success, _ = await run_shell_command(cmd, working_dir)
311
+ label = ctx.repo_config.test_cmd
312
+ if test_filter:
313
+ label += f" {ctx.repo_config.test_filter_flag} {test_filter}"
314
+ return CheckResult("Tests", CheckStatus.PASS if success else CheckStatus.FAIL, command=label)
315
+
316
+ # Prefer justfile recipes
317
+ if has_just_recipe("test", working_dir):
318
+ cmd = ["just", "test"]
319
+ label = "just test"
320
+ if test_filter:
321
+ cmd.append(test_filter)
322
+ label += f" {test_filter}"
323
+ success, _ = await run_command(cmd, working_dir)
324
+ return CheckResult("Tests", CheckStatus.PASS if success else CheckStatus.FAIL, command=label)
325
+
326
+ project_type = detect_project_type(working_dir)
327
+
328
+ if project_type == "node" and has_npm_script("test", working_dir):
329
+ # Check for pnpm workspace (monorepo)
330
+ pnpm_workspace = (working_dir / "pnpm-workspace.yaml").exists()
331
+ has_pnpm = shutil.which("pnpm") is not None
332
+
333
+ if pnpm_workspace and has_pnpm:
334
+ if ctx.fast_mode:
335
+ cmd = "pnpm -r --filter '!@pennyfarthing/cyclist' test"
336
+ label = "pnpm test (fast mode - skipping cyclist)"
337
+ else:
338
+ cmd = "pnpm -r test"
339
+ label = "pnpm test"
340
+ else:
341
+ cmd = "npm test"
342
+ label = "npm test"
343
+
344
+ if test_filter:
345
+ cmd += f' -- -t "{test_filter}"'
346
+ label += f" -t {test_filter}"
347
+
348
+ success, _ = await run_shell_command(cmd, working_dir)
349
+ return CheckResult("Tests", CheckStatus.PASS if success else CheckStatus.FAIL, command=label)
350
+
351
+ if project_type == "go":
352
+ cmd = "go test ./..."
353
+ label = "go test ./..."
354
+ if test_filter:
355
+ cmd = f'go test -run "{test_filter}" ./...'
356
+ label = f"go test -run {test_filter} ./..."
357
+ success, _ = await run_shell_command(cmd, working_dir)
358
+ return CheckResult("Tests", CheckStatus.PASS if success else CheckStatus.FAIL, command=label)
359
+
360
+ jest_path = working_dir / "node_modules" / ".bin" / "jest"
361
+ if jest_path.exists():
362
+ cmd = [str(jest_path)]
363
+ label = "jest"
364
+ if test_filter:
365
+ cmd.extend(["-t", test_filter])
366
+ label += f" -t {test_filter}"
367
+ success, _ = await run_command(cmd, working_dir)
368
+ return CheckResult("Tests", CheckStatus.PASS if success else CheckStatus.FAIL, command=label)
369
+
370
+ return CheckResult("Tests", CheckStatus.SKIP, message="no test command configured")
371
+
372
+
373
+ def print_result(result: CheckResult, stats: CheckStats) -> None:
374
+ """Print a check result and update stats."""
375
+ stats.record(result.status)
376
+
377
+ if result.status == CheckStatus.PASS:
378
+ print_pass(result.name, result.command)
379
+ elif result.status == CheckStatus.FAIL:
380
+ print_fail(result.name, result.command)
381
+ else:
382
+ print_skip(result.name, result.message or "")
383
+
384
+
385
+ def print_summary(stats: CheckStats, project_type: str) -> int:
386
+ """Print summary and return exit code."""
387
+ print_section("Summary")
388
+ print()
389
+ print(f"Checks run: {stats.run}")
390
+ print(f"Checks passed: {COLORS.GREEN}{stats.passed}{COLORS.NC}")
391
+
392
+ if stats.failed > 0:
393
+ print(f"Checks failed: {COLORS.RED}{stats.failed}{COLORS.NC}")
394
+ else:
395
+ print(f"Checks failed: {stats.failed}")
396
+
397
+ if stats.skipped > 0:
398
+ print(f"Checks skipped: {COLORS.YELLOW}{stats.skipped}{COLORS.NC}")
399
+
400
+ print()
401
+
402
+ if stats.failed > 0:
403
+ print(f"{COLORS.RED}FAILED{COLORS.NC} - {stats.failed} check(s) failed")
404
+ print("Fix issues before handoff to Reviewer.")
405
+ return 1
406
+ elif stats.run == 0:
407
+ print(f"{COLORS.YELLOW}WARNING{COLORS.NC} - No checks ran (project type: {project_type})")
408
+ print("Consider adding lint/test scripts to package.json or justfile.")
409
+ return 0
410
+ else:
411
+ print(f"{COLORS.GREEN}PASSED{COLORS.NC} - All checks passed")
412
+ return 0
413
+
414
+
415
+ async def main() -> int:
416
+ parser = argparse.ArgumentParser(
417
+ description="Quality gate runner for pre-handoff verification"
418
+ )
419
+ parser.add_argument("--skip-check", action="store_true",
420
+ help="Skip all checks (emergency bypass)")
421
+ parser.add_argument("--tests-only", action="store_true",
422
+ help="Run only tests, skip lint and typecheck")
423
+ parser.add_argument("--filter", dest="test_filter", default="",
424
+ help="Filter tests by pattern")
425
+ parser.add_argument("--repo", dest="target_repo", default="",
426
+ help="Run checks in specific repo subdirectory")
427
+ parser.add_argument("--no-lint", action="store_true",
428
+ help="Skip lint check")
429
+ parser.add_argument("--no-typecheck", action="store_true",
430
+ help="Skip type check")
431
+ parser.add_argument("--fast", action="store_true",
432
+ help="Skip slow packages for rapid iteration")
433
+
434
+ args = parser.parse_args()
435
+
436
+ # Handle --skip-check
437
+ if args.skip_check:
438
+ print("Quality checks skipped by --skip-check flag")
439
+ print()
440
+ print("WARNING: Skipping checks is for emergencies only.")
441
+ print("Ensure checks pass before merging PR.")
442
+ return 0
443
+
444
+ # Handle --tests-only
445
+ no_lint = args.no_lint or args.tests_only
446
+ no_typecheck = args.no_typecheck or args.tests_only
447
+
448
+ # Find project root
449
+ project_root = find_project_root()
450
+
451
+ # Handle --repo
452
+ if args.target_repo:
453
+ working_dir = project_root / args.target_repo
454
+ if not working_dir.is_dir():
455
+ print(f"Error: Repo directory not found: {working_dir}")
456
+ return 1
457
+ else:
458
+ working_dir = project_root
459
+
460
+ # Create context
461
+ ctx = CheckContext(
462
+ project_root=project_root,
463
+ working_dir=working_dir,
464
+ target_repo=args.target_repo,
465
+ test_filter=args.test_filter,
466
+ no_lint=no_lint,
467
+ no_typecheck=no_typecheck,
468
+ fast_mode=args.fast
469
+ )
470
+
471
+ # Print header
472
+ print()
473
+ print("Quality Gate Check")
474
+ print("==================")
475
+ print(f"Project: {project_root}")
476
+ if args.target_repo:
477
+ print(f"Repo: {args.target_repo}")
478
+ print(f"Working dir: {working_dir}")
479
+ if args.fast:
480
+ print(f"{COLORS.YELLOW}Mode: FAST (skipping slow packages){COLORS.NC}")
481
+
482
+ project_type = detect_project_type(working_dir)
483
+
484
+ # Run lint and typecheck concurrently, then tests
485
+ # (Tests often depend on lint/typecheck passing in CI, but we run all for reporting)
486
+ print_section("Lint")
487
+ lint_result = await run_lint(ctx)
488
+ print_result(lint_result, ctx.stats)
489
+
490
+ print_section("Type Check")
491
+ typecheck_result = await run_typecheck(ctx)
492
+ print_result(typecheck_result, ctx.stats)
493
+
494
+ print_section("Tests")
495
+ test_result = await run_tests(ctx)
496
+ print_result(test_result, ctx.stats)
497
+
498
+ return print_summary(ctx.stats, project_type)
499
+
500
+
501
+ if __name__ == "__main__":
502
+ sys.exit(asyncio.run(main()))
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+ # check.sh - Quality gate runner for pre-handoff verification
3
+ #
4
+ # Story 21-1: /check command with dev-handoff integration
5
+ #
6
+ # Usage: ./scripts/check.sh [OPTIONS]
7
+ #
8
+ # Options:
9
+ # --skip-check Skip all checks (emergency bypass)
10
+ # --tests-only Run only tests, skip lint and typecheck
11
+ # --filter PATTERN Filter tests by pattern (passed to test runner)
12
+ # --repo REPO Run checks in specific repo subdirectory
13
+ # --no-lint Skip lint check
14
+ # --no-typecheck Skip type check
15
+ # --fast Skip slow packages (cyclist/Electron) for rapid iteration
16
+ #
17
+ # Runs lint, type check, and tests. Reports pass/fail status.
18
+ # Returns exit code 0 on all passing, non-zero on any failure.
19
+
20
+ set -euo pipefail
21
+
22
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+
24
+ exec python3 "$SCRIPT_DIR/check.py" "$@"