yeaboi 2.8.0__tar.gz

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 (372) hide show
  1. yeaboi-2.8.0/.env.example +126 -0
  2. yeaboi-2.8.0/.github/workflows/auto-version.yml +107 -0
  3. yeaboi-2.8.0/.github/workflows/ci.yml +79 -0
  4. yeaboi-2.8.0/.github/workflows/claude-code-review.yml +48 -0
  5. yeaboi-2.8.0/.github/workflows/claude.yml +49 -0
  6. yeaboi-2.8.0/.github/workflows/publish.yml +86 -0
  7. yeaboi-2.8.0/.github/workflows/smoke.yml +44 -0
  8. yeaboi-2.8.0/.gitignore +62 -0
  9. yeaboi-2.8.0/.pre-commit-config.yaml +29 -0
  10. yeaboi-2.8.0/CLAUDE.md +600 -0
  11. yeaboi-2.8.0/LICENSE +21 -0
  12. yeaboi-2.8.0/Makefile +84 -0
  13. yeaboi-2.8.0/PKG-INFO +2344 -0
  14. yeaboi-2.8.0/README.md +2285 -0
  15. yeaboi-2.8.0/SCRUM.md.example +51 -0
  16. yeaboi-2.8.0/TELEMETRY.md +132 -0
  17. yeaboi-2.8.0/TODO.md +1347 -0
  18. yeaboi-2.8.0/docs/CNAME +1 -0
  19. yeaboi-2.8.0/docs/ScrumTeamTraining.pdf +0 -0
  20. yeaboi-2.8.0/docs/banner.jpg +0 -0
  21. yeaboi-2.8.0/docs/demo.gif +0 -0
  22. yeaboi-2.8.0/docs/graph.png +0 -0
  23. yeaboi-2.8.0/docs/index.html +299 -0
  24. yeaboi-2.8.0/docs/lightsail-setup/01-create-instance.png +0 -0
  25. yeaboi-2.8.0/docs/lightsail-setup/02-static-ip.png +0 -0
  26. yeaboi-2.8.0/docs/lightsail-setup/03-bedrock-setup.png +0 -0
  27. yeaboi-2.8.0/docs/lightsail-setup/04-pair-browser.png +0 -0
  28. yeaboi-2.8.0/docs/lightsail-setup/05-dashboard.png +0 -0
  29. yeaboi-2.8.0/docs/lightsail-setup/06-install-scrum-agent.png +0 -0
  30. yeaboi-2.8.0/docs/lightsail-setup/07-setup-bedrock.png +0 -0
  31. yeaboi-2.8.0/docs/lightsail-setup/08-headless-test.png +0 -0
  32. yeaboi-2.8.0/docs/lightsail-setup/09-install-skill.png +0 -0
  33. yeaboi-2.8.0/docs/lightsail-setup/10-skill-dashboard.png +0 -0
  34. yeaboi-2.8.0/docs/lightsail-setup/11-skill-intake.png +0 -0
  35. yeaboi-2.8.0/docs/lightsail-setup/12-skill-output.png +0 -0
  36. yeaboi-2.8.0/docs/lightsail-setup/13-slack-channel-add.png +0 -0
  37. yeaboi-2.8.0/docs/lightsail-setup/14-slack-channel-configure.png +0 -0
  38. yeaboi-2.8.0/docs/lightsail-setup/15-slack-openclaw-invite.png +0 -0
  39. yeaboi-2.8.0/docs/lightsail-setup/16-slack-intake.png +0 -0
  40. yeaboi-2.8.0/docs/lightsail-setup/17-slack-output-message.png +0 -0
  41. yeaboi-2.8.0/docs/lightsail-setup/18-slack-output-canvas.png +0 -0
  42. yeaboi-2.8.0/docs/screenshots/.gitkeep +0 -0
  43. yeaboi-2.8.0/docs/screenshots/analysis-results.png +0 -0
  44. yeaboi-2.8.0/docs/screenshots/epic-review.png +0 -0
  45. yeaboi-2.8.0/docs/screenshots/html-export.png +0 -0
  46. yeaboi-2.8.0/docs/screenshots/member-multiselect-planning.png +0 -0
  47. yeaboi-2.8.0/docs/screenshots/member-multiselect.png +0 -0
  48. yeaboi-2.8.0/docs/screenshots/profile-picker.png +0 -0
  49. yeaboi-2.8.0/docs/screenshots/settings-page.png +0 -0
  50. yeaboi-2.8.0/docs/screenshots/smart-intake-autofill.png +0 -0
  51. yeaboi-2.8.0/docs/screenshots/team-members.png +0 -0
  52. yeaboi-2.8.0/docs/screenshots/usage-page.png +0 -0
  53. yeaboi-2.8.0/packaging/scrum-agent-shim/README.md +22 -0
  54. yeaboi-2.8.0/packaging/scrum-agent-shim/pyproject.toml +39 -0
  55. yeaboi-2.8.0/pyproject.toml +115 -0
  56. yeaboi-2.8.0/sample_projects/datadog_bits/datadog-bits-ai-sre-plan.html +1136 -0
  57. yeaboi-2.8.0/sample_projects/datadog_bits/datadog-bits-ai-sre-plan.md +989 -0
  58. yeaboi-2.8.0/sample_projects/datadog_workflow/datadog-eks-automation-plan.html +537 -0
  59. yeaboi-2.8.0/sample_projects/datadog_workflow/datadog-eks-automation-plan.md +353 -0
  60. yeaboi-2.8.0/scripts/bump_version.py +85 -0
  61. yeaboi-2.8.0/scripts/generate_graph_png.py +42 -0
  62. yeaboi-2.8.0/scripts/seed_mock_data.py +245 -0
  63. yeaboi-2.8.0/skills +1 -0
  64. yeaboi-2.8.0/src/yeaboi/__init__.py +74 -0
  65. yeaboi-2.8.0/src/yeaboi/agent/__init__.py +73 -0
  66. yeaboi-2.8.0/src/yeaboi/agent/ceremony_history.py +255 -0
  67. yeaboi-2.8.0/src/yeaboi/agent/graph.py +296 -0
  68. yeaboi-2.8.0/src/yeaboi/agent/llm.py +231 -0
  69. yeaboi-2.8.0/src/yeaboi/agent/nodes.py +8367 -0
  70. yeaboi-2.8.0/src/yeaboi/agent/repo_signals.py +504 -0
  71. yeaboi-2.8.0/src/yeaboi/agent/state.py +993 -0
  72. yeaboi-2.8.0/src/yeaboi/azdevops_sync.py +692 -0
  73. yeaboi-2.8.0/src/yeaboi/cli.py +1301 -0
  74. yeaboi-2.8.0/src/yeaboi/config.py +519 -0
  75. yeaboi-2.8.0/src/yeaboi/formatters.py +637 -0
  76. yeaboi-2.8.0/src/yeaboi/html_exporter.py +827 -0
  77. yeaboi-2.8.0/src/yeaboi/input_guardrails.py +354 -0
  78. yeaboi-2.8.0/src/yeaboi/jira_sync.py +714 -0
  79. yeaboi-2.8.0/src/yeaboi/json_exporter.py +115 -0
  80. yeaboi-2.8.0/src/yeaboi/music.py +353 -0
  81. yeaboi-2.8.0/src/yeaboi/output_guardrails.py +239 -0
  82. yeaboi-2.8.0/src/yeaboi/paths.py +334 -0
  83. yeaboi-2.8.0/src/yeaboi/performance/__init__.py +48 -0
  84. yeaboi-2.8.0/src/yeaboi/performance/activity.py +140 -0
  85. yeaboi-2.8.0/src/yeaboi/performance/context.py +101 -0
  86. yeaboi-2.8.0/src/yeaboi/performance/delivery.py +83 -0
  87. yeaboi-2.8.0/src/yeaboi/performance/engine.py +483 -0
  88. yeaboi-2.8.0/src/yeaboi/performance/export.py +203 -0
  89. yeaboi-2.8.0/src/yeaboi/performance/references/competency_framework.md +42 -0
  90. yeaboi-2.8.0/src/yeaboi/performance/render.py +189 -0
  91. yeaboi-2.8.0/src/yeaboi/performance/roster.py +108 -0
  92. yeaboi-2.8.0/src/yeaboi/performance/store.py +359 -0
  93. yeaboi-2.8.0/src/yeaboi/persistence.py +959 -0
  94. yeaboi-2.8.0/src/yeaboi/prompts/__init__.py +27 -0
  95. yeaboi-2.8.0/src/yeaboi/prompts/analyzer.py +267 -0
  96. yeaboi-2.8.0/src/yeaboi/prompts/feature_generator.py +187 -0
  97. yeaboi-2.8.0/src/yeaboi/prompts/intake.py +638 -0
  98. yeaboi-2.8.0/src/yeaboi/prompts/performance.py +201 -0
  99. yeaboi-2.8.0/src/yeaboi/prompts/reporting.py +88 -0
  100. yeaboi-2.8.0/src/yeaboi/prompts/retro.py +64 -0
  101. yeaboi-2.8.0/src/yeaboi/prompts/sprint_planner.py +242 -0
  102. yeaboi-2.8.0/src/yeaboi/prompts/standup.py +76 -0
  103. yeaboi-2.8.0/src/yeaboi/prompts/story_writer.py +317 -0
  104. yeaboi-2.8.0/src/yeaboi/prompts/system.py +107 -0
  105. yeaboi-2.8.0/src/yeaboi/prompts/task_decomposer.py +211 -0
  106. yeaboi-2.8.0/src/yeaboi/questionnaire_io.py +196 -0
  107. yeaboi-2.8.0/src/yeaboi/repl/__init__.py +1316 -0
  108. yeaboi-2.8.0/src/yeaboi/repl/_intake_menu.py +93 -0
  109. yeaboi-2.8.0/src/yeaboi/repl/_io.py +573 -0
  110. yeaboi-2.8.0/src/yeaboi/repl/_mode_menu.py +66 -0
  111. yeaboi-2.8.0/src/yeaboi/repl/_questionnaire.py +396 -0
  112. yeaboi-2.8.0/src/yeaboi/repl/_review.py +162 -0
  113. yeaboi-2.8.0/src/yeaboi/repl/_ui.py +177 -0
  114. yeaboi-2.8.0/src/yeaboi/reporting/__init__.py +55 -0
  115. yeaboi-2.8.0/src/yeaboi/reporting/activity.py +165 -0
  116. yeaboi-2.8.0/src/yeaboi/reporting/engine.py +375 -0
  117. yeaboi-2.8.0/src/yeaboi/reporting/export.py +192 -0
  118. yeaboi-2.8.0/src/yeaboi/reporting/presentation.py +285 -0
  119. yeaboi-2.8.0/src/yeaboi/reporting/render.py +114 -0
  120. yeaboi-2.8.0/src/yeaboi/reporting/sprints.py +163 -0
  121. yeaboi-2.8.0/src/yeaboi/reporting/store.py +196 -0
  122. yeaboi-2.8.0/src/yeaboi/retro/__init__.py +29 -0
  123. yeaboi-2.8.0/src/yeaboi/retro/board.py +428 -0
  124. yeaboi-2.8.0/src/yeaboi/retro/engine.py +112 -0
  125. yeaboi-2.8.0/src/yeaboi/retro/export.py +164 -0
  126. yeaboi-2.8.0/src/yeaboi/retro/page.py +856 -0
  127. yeaboi-2.8.0/src/yeaboi/retro/server.py +392 -0
  128. yeaboi-2.8.0/src/yeaboi/retro/store.py +212 -0
  129. yeaboi-2.8.0/src/yeaboi/retro/tunnel.py +229 -0
  130. yeaboi-2.8.0/src/yeaboi/sessions.py +767 -0
  131. yeaboi-2.8.0/src/yeaboi/setup_wizard.py +288 -0
  132. yeaboi-2.8.0/src/yeaboi/skills/__init__.py +0 -0
  133. yeaboi-2.8.0/src/yeaboi/skills/scrum-planner/README.md +159 -0
  134. yeaboi-2.8.0/src/yeaboi/skills/scrum-planner/SKILL.md +338 -0
  135. yeaboi-2.8.0/src/yeaboi/skills/scrum-planner/references/cli-and-generation.md +85 -0
  136. yeaboi-2.8.0/src/yeaboi/skills/scrum-planner/references/output-and-review.md +125 -0
  137. yeaboi-2.8.0/src/yeaboi/skills/scrum-planner/scripts/canvas.py +233 -0
  138. yeaboi-2.8.0/src/yeaboi/skills/scrum-planner/scripts/canvas_push.py +231 -0
  139. yeaboi-2.8.0/src/yeaboi/standup/__init__.py +26 -0
  140. yeaboi-2.8.0/src/yeaboi/standup/collector.py +203 -0
  141. yeaboi-2.8.0/src/yeaboi/standup/confidence.py +171 -0
  142. yeaboi-2.8.0/src/yeaboi/standup/delivery.py +229 -0
  143. yeaboi-2.8.0/src/yeaboi/standup/engine.py +358 -0
  144. yeaboi-2.8.0/src/yeaboi/standup/errors.py +26 -0
  145. yeaboi-2.8.0/src/yeaboi/standup/export.py +201 -0
  146. yeaboi-2.8.0/src/yeaboi/standup/interactive.py +119 -0
  147. yeaboi-2.8.0/src/yeaboi/standup/render.py +125 -0
  148. yeaboi-2.8.0/src/yeaboi/standup/scheduler.py +297 -0
  149. yeaboi-2.8.0/src/yeaboi/standup/sprint_context.py +104 -0
  150. yeaboi-2.8.0/src/yeaboi/standup/store.py +356 -0
  151. yeaboi-2.8.0/src/yeaboi/team_profile.py +687 -0
  152. yeaboi-2.8.0/src/yeaboi/team_profile_exporter.py +2237 -0
  153. yeaboi-2.8.0/src/yeaboi/telemetry.py +256 -0
  154. yeaboi-2.8.0/src/yeaboi/tools/__init__.py +135 -0
  155. yeaboi-2.8.0/src/yeaboi/tools/azure_devops.py +1015 -0
  156. yeaboi-2.8.0/src/yeaboi/tools/calendar_tools.py +308 -0
  157. yeaboi-2.8.0/src/yeaboi/tools/codebase.py +559 -0
  158. yeaboi-2.8.0/src/yeaboi/tools/confluence.py +439 -0
  159. yeaboi-2.8.0/src/yeaboi/tools/github.py +434 -0
  160. yeaboi-2.8.0/src/yeaboi/tools/jira.py +835 -0
  161. yeaboi-2.8.0/src/yeaboi/tools/llm_tools.py +158 -0
  162. yeaboi-2.8.0/src/yeaboi/tools/local_git.py +83 -0
  163. yeaboi-2.8.0/src/yeaboi/tools/notion.py +484 -0
  164. yeaboi-2.8.0/src/yeaboi/tools/team_learning.py +5421 -0
  165. yeaboi-2.8.0/src/yeaboi/ui/__init__.py +2 -0
  166. yeaboi-2.8.0/src/yeaboi/ui/mode_select/__init__.py +4967 -0
  167. yeaboi-2.8.0/src/yeaboi/ui/mode_select/screens/__init__.py +1 -0
  168. yeaboi-2.8.0/src/yeaboi/ui/mode_select/screens/_project_cards.py +588 -0
  169. yeaboi-2.8.0/src/yeaboi/ui/mode_select/screens/_project_list_screen.py +770 -0
  170. yeaboi-2.8.0/src/yeaboi/ui/mode_select/screens/_screens.py +381 -0
  171. yeaboi-2.8.0/src/yeaboi/ui/mode_select/screens/_screens_secondary.py +4373 -0
  172. yeaboi-2.8.0/src/yeaboi/ui/provider_select/__init__.py +893 -0
  173. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_config.py +41 -0
  174. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_constants.py +237 -0
  175. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_nav.py +63 -0
  176. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_phase_confluence.py +261 -0
  177. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_phase_issue_tracking.py +387 -0
  178. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_phase_notion.py +241 -0
  179. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_transitions.py +95 -0
  180. yeaboi-2.8.0/src/yeaboi/ui/provider_select/_verification.py +508 -0
  181. yeaboi-2.8.0/src/yeaboi/ui/provider_select/screens/__init__.py +1 -0
  182. yeaboi-2.8.0/src/yeaboi/ui/provider_select/screens/_screens.py +565 -0
  183. yeaboi-2.8.0/src/yeaboi/ui/provider_select/screens/_screens_vc.py +378 -0
  184. yeaboi-2.8.0/src/yeaboi/ui/session/__init__.py +389 -0
  185. yeaboi-2.8.0/src/yeaboi/ui/session/_dry_run.py +98 -0
  186. yeaboi-2.8.0/src/yeaboi/ui/session/_renderers.py +1179 -0
  187. yeaboi-2.8.0/src/yeaboi/ui/session/_utils.py +394 -0
  188. yeaboi-2.8.0/src/yeaboi/ui/session/editor/__init__.py +1 -0
  189. yeaboi-2.8.0/src/yeaboi/ui/session/editor/_editor.py +717 -0
  190. yeaboi-2.8.0/src/yeaboi/ui/session/editor/_editor_artifacts.py +529 -0
  191. yeaboi-2.8.0/src/yeaboi/ui/session/editor/_editor_core.py +457 -0
  192. yeaboi-2.8.0/src/yeaboi/ui/session/phases/__init__.py +1 -0
  193. yeaboi-2.8.0/src/yeaboi/ui/session/phases/_phases.py +1685 -0
  194. yeaboi-2.8.0/src/yeaboi/ui/session/phases/_phases_intake.py +659 -0
  195. yeaboi-2.8.0/src/yeaboi/ui/session/phases/_phases_review.py +323 -0
  196. yeaboi-2.8.0/src/yeaboi/ui/session/screens/__init__.py +1 -0
  197. yeaboi-2.8.0/src/yeaboi/ui/session/screens/_accordion.py +508 -0
  198. yeaboi-2.8.0/src/yeaboi/ui/session/screens/_screens.py +209 -0
  199. yeaboi-2.8.0/src/yeaboi/ui/session/screens/_screens_input.py +386 -0
  200. yeaboi-2.8.0/src/yeaboi/ui/session/screens/_screens_pipeline.py +543 -0
  201. yeaboi-2.8.0/src/yeaboi/ui/shared/__init__.py +43 -0
  202. yeaboi-2.8.0/src/yeaboi/ui/shared/_animations.py +164 -0
  203. yeaboi-2.8.0/src/yeaboi/ui/shared/_ascii_font.py +67 -0
  204. yeaboi-2.8.0/src/yeaboi/ui/shared/_components.py +378 -0
  205. yeaboi-2.8.0/src/yeaboi/ui/shared/_input.py +313 -0
  206. yeaboi-2.8.0/src/yeaboi/ui/shared/_music_bar.py +159 -0
  207. yeaboi-2.8.0/src/yeaboi/ui/shared/_tips.py +107 -0
  208. yeaboi-2.8.0/src/yeaboi/ui/shared/_voice_input.py +207 -0
  209. yeaboi-2.8.0/src/yeaboi/ui/shared/_wordmarks.py +150 -0
  210. yeaboi-2.8.0/src/yeaboi/ui/splash.py +331 -0
  211. yeaboi-2.8.0/src/yeaboi/voice.py +196 -0
  212. yeaboi-2.8.0/tests/__init__.py +0 -0
  213. yeaboi-2.8.0/tests/_node_helpers.py +282 -0
  214. yeaboi-2.8.0/tests/conftest.py +93 -0
  215. yeaboi-2.8.0/tests/contract/__init__.py +0 -0
  216. yeaboi-2.8.0/tests/contract/cassettes/test_confluence_contract/TestConfluenceCreatePageContract.test_create_page_returns_id_and_url.yaml +18 -0
  217. yeaboi-2.8.0/tests/contract/cassettes/test_confluence_contract/TestConfluenceErrorResponsesContract.test_401_bad_token.yaml +18 -0
  218. yeaboi-2.8.0/tests/contract/cassettes/test_confluence_contract/TestConfluenceErrorResponsesContract.test_404_missing_space.yaml +18 -0
  219. yeaboi-2.8.0/tests/contract/cassettes/test_confluence_contract/TestConfluenceReadPageContract.test_read_page_by_id_strips_html.yaml +18 -0
  220. yeaboi-2.8.0/tests/contract/cassettes/test_confluence_contract/TestConfluenceReadSpaceContract.test_read_space_lists_pages.yaml +18 -0
  221. yeaboi-2.8.0/tests/contract/cassettes/test_confluence_contract/TestConfluenceSearchDocsContract.test_search_returns_titles_and_urls.yaml +18 -0
  222. yeaboi-2.8.0/tests/contract/cassettes/test_github_contract/TestGithubErrorResponsesContract.test_401_bad_token.yaml +18 -0
  223. yeaboi-2.8.0/tests/contract/cassettes/test_github_contract/TestGithubErrorResponsesContract.test_404_missing_repo.yaml +18 -0
  224. yeaboi-2.8.0/tests/contract/cassettes/test_github_contract/TestGithubListIssuesContract.test_list_issues_with_labels.yaml +34 -0
  225. yeaboi-2.8.0/tests/contract/cassettes/test_github_contract/TestGithubReadFileContract.test_read_file_decodes_content.yaml +34 -0
  226. yeaboi-2.8.0/tests/contract/cassettes/test_github_contract/TestGithubReadReadmeContract.test_read_readme_with_contributing.yaml +50 -0
  227. yeaboi-2.8.0/tests/contract/cassettes/test_github_contract/TestGithubReadRepoContract.test_read_repo_tree_and_languages.yaml +50 -0
  228. yeaboi-2.8.0/tests/contract/cassettes/test_jira_contract/TestJiraCreateEpicContract.test_create_epic_happy_path.yaml +34 -0
  229. yeaboi-2.8.0/tests/contract/cassettes/test_jira_contract/TestJiraCreateSprintContract.test_create_sprint_with_dates_and_goal.yaml +18 -0
  230. yeaboi-2.8.0/tests/contract/cassettes/test_jira_contract/TestJiraCreateStoryContract.test_create_story_with_points_and_epic_link.yaml +34 -0
  231. yeaboi-2.8.0/tests/contract/cassettes/test_jira_contract/TestJiraErrorResponsesContract.test_401_bad_token.yaml +18 -0
  232. yeaboi-2.8.0/tests/contract/cassettes/test_jira_contract/TestJiraErrorResponsesContract.test_404_missing_project.yaml +18 -0
  233. yeaboi-2.8.0/tests/contract/cassettes/test_jira_contract/TestJiraReadBoardContract.test_read_board_happy_path.yaml +130 -0
  234. yeaboi-2.8.0/tests/contract/cassettes/test_notion_contract/TestNotionCreatePageContract.test_create_page_returns_id_and_url.yaml +18 -0
  235. yeaboi-2.8.0/tests/contract/cassettes/test_notion_contract/TestNotionErrorResponsesContract.test_401_bad_token.yaml +18 -0
  236. yeaboi-2.8.0/tests/contract/cassettes/test_notion_contract/TestNotionReadDatabaseContract.test_read_database_lists_entries.yaml +18 -0
  237. yeaboi-2.8.0/tests/contract/cassettes/test_notion_contract/TestNotionReadPageContract.test_read_page_flattens_blocks.yaml +34 -0
  238. yeaboi-2.8.0/tests/contract/cassettes/test_notion_contract/TestNotionSearchContract.test_search_returns_titles_and_urls.yaml +18 -0
  239. yeaboi-2.8.0/tests/contract/test_azure_devops_contract.py +250 -0
  240. yeaboi-2.8.0/tests/contract/test_confluence_contract.py +181 -0
  241. yeaboi-2.8.0/tests/contract/test_github_contract.py +194 -0
  242. yeaboi-2.8.0/tests/contract/test_jira_contract.py +227 -0
  243. yeaboi-2.8.0/tests/contract/test_llm_provider_contract.py +588 -0
  244. yeaboi-2.8.0/tests/contract/test_notion_contract.py +97 -0
  245. yeaboi-2.8.0/tests/contract/test_schema_validation.py +554 -0
  246. yeaboi-2.8.0/tests/fixtures/SCRUM.md +56 -0
  247. yeaboi-2.8.0/tests/fixtures/scrum-questionnaire-answers.md +149 -0
  248. yeaboi-2.8.0/tests/golden/__init__.py +0 -0
  249. yeaboi-2.8.0/tests/golden/conftest.py +10 -0
  250. yeaboi-2.8.0/tests/golden/datasets.py +304 -0
  251. yeaboi-2.8.0/tests/golden/test_golden.py +378 -0
  252. yeaboi-2.8.0/tests/integration/__init__.py +0 -0
  253. yeaboi-2.8.0/tests/integration/conftest.py +57 -0
  254. yeaboi-2.8.0/tests/integration/test_cli.py +1088 -0
  255. yeaboi-2.8.0/tests/integration/test_e2e_graph.py +756 -0
  256. yeaboi-2.8.0/tests/integration/test_e2e_repl.py +565 -0
  257. yeaboi-2.8.0/tests/integration/test_graph.py +727 -0
  258. yeaboi-2.8.0/tests/integration/test_graph_topology.py +272 -0
  259. yeaboi-2.8.0/tests/integration/test_integration.py +780 -0
  260. yeaboi-2.8.0/tests/integration/test_react_loop.py +452 -0
  261. yeaboi-2.8.0/tests/integration/test_repl.py +2774 -0
  262. yeaboi-2.8.0/tests/integration/test_sessions.py +733 -0
  263. yeaboi-2.8.0/tests/smoke/__init__.py +0 -0
  264. yeaboi-2.8.0/tests/smoke/conftest.py +79 -0
  265. yeaboi-2.8.0/tests/smoke/test_smoke.py +239 -0
  266. yeaboi-2.8.0/tests/test_accordion.py +304 -0
  267. yeaboi-2.8.0/tests/test_mode_select.py +297 -0
  268. yeaboi-2.8.0/tests/test_persistence.py +486 -0
  269. yeaboi-2.8.0/tests/test_session.py +735 -0
  270. yeaboi-2.8.0/tests/test_splash.py +101 -0
  271. yeaboi-2.8.0/tests/unit/__init__.py +0 -0
  272. yeaboi-2.8.0/tests/unit/__snapshots__/test_formatters.ambr +389 -0
  273. yeaboi-2.8.0/tests/unit/guardrails/__init__.py +0 -0
  274. yeaboi-2.8.0/tests/unit/guardrails/test_guardrails_adversarial.py +281 -0
  275. yeaboi-2.8.0/tests/unit/guardrails/test_input_guardrails.py +394 -0
  276. yeaboi-2.8.0/tests/unit/guardrails/test_output_guardrails.py +203 -0
  277. yeaboi-2.8.0/tests/unit/guardrails/test_tool_guardrails.py +96 -0
  278. yeaboi-2.8.0/tests/unit/nodes/__init__.py +0 -0
  279. yeaboi-2.8.0/tests/unit/nodes/test_agent_core.py +531 -0
  280. yeaboi-2.8.0/tests/unit/nodes/test_analyzer.py +1224 -0
  281. yeaboi-2.8.0/tests/unit/nodes/test_capacity_check.py +875 -0
  282. yeaboi-2.8.0/tests/unit/nodes/test_ceremony_history.py +219 -0
  283. yeaboi-2.8.0/tests/unit/nodes/test_ceremony_integration.py +120 -0
  284. yeaboi-2.8.0/tests/unit/nodes/test_feature_generator.py +389 -0
  285. yeaboi-2.8.0/tests/unit/nodes/test_intake.py +3777 -0
  286. yeaboi-2.8.0/tests/unit/nodes/test_low_code.py +187 -0
  287. yeaboi-2.8.0/tests/unit/nodes/test_parser_adversarial.py +354 -0
  288. yeaboi-2.8.0/tests/unit/nodes/test_repo_signals.py +230 -0
  289. yeaboi-2.8.0/tests/unit/nodes/test_review.py +383 -0
  290. yeaboi-2.8.0/tests/unit/nodes/test_route_entry.py +298 -0
  291. yeaboi-2.8.0/tests/unit/nodes/test_small_project.py +238 -0
  292. yeaboi-2.8.0/tests/unit/nodes/test_sprint_planner.py +989 -0
  293. yeaboi-2.8.0/tests/unit/nodes/test_sprint_selector.py +42 -0
  294. yeaboi-2.8.0/tests/unit/nodes/test_story_writer.py +937 -0
  295. yeaboi-2.8.0/tests/unit/nodes/test_task_decomposer.py +822 -0
  296. yeaboi-2.8.0/tests/unit/prompts/__init__.py +0 -0
  297. yeaboi-2.8.0/tests/unit/prompts/test_analyzer_prompt.py +169 -0
  298. yeaboi-2.8.0/tests/unit/prompts/test_feature_generator_prompt.py +168 -0
  299. yeaboi-2.8.0/tests/unit/prompts/test_prompts_team_calibration.py +113 -0
  300. yeaboi-2.8.0/tests/unit/prompts/test_sprint_planner_prompt.py +115 -0
  301. yeaboi-2.8.0/tests/unit/prompts/test_story_writer_prompt.py +246 -0
  302. yeaboi-2.8.0/tests/unit/prompts/test_system_prompt.py +85 -0
  303. yeaboi-2.8.0/tests/unit/prompts/test_task_decomposer_prompt.py +115 -0
  304. yeaboi-2.8.0/tests/unit/test_analysis_generation.py +418 -0
  305. yeaboi-2.8.0/tests/unit/test_analysis_screens.py +830 -0
  306. yeaboi-2.8.0/tests/unit/test_analysis_sessions.py +293 -0
  307. yeaboi-2.8.0/tests/unit/test_azdevops_sync.py +398 -0
  308. yeaboi-2.8.0/tests/unit/test_bump_version.py +66 -0
  309. yeaboi-2.8.0/tests/unit/test_config.py +327 -0
  310. yeaboi-2.8.0/tests/unit/test_fixtures.py +159 -0
  311. yeaboi-2.8.0/tests/unit/test_formatters.py +381 -0
  312. yeaboi-2.8.0/tests/unit/test_jira_sync.py +410 -0
  313. yeaboi-2.8.0/tests/unit/test_json_exporter.py +142 -0
  314. yeaboi-2.8.0/tests/unit/test_llm.py +317 -0
  315. yeaboi-2.8.0/tests/unit/test_music.py +239 -0
  316. yeaboi-2.8.0/tests/unit/test_music_bar.py +135 -0
  317. yeaboi-2.8.0/tests/unit/test_performance_activity.py +77 -0
  318. yeaboi-2.8.0/tests/unit/test_performance_context.py +35 -0
  319. yeaboi-2.8.0/tests/unit/test_performance_engine.py +168 -0
  320. yeaboi-2.8.0/tests/unit/test_performance_render_export.py +113 -0
  321. yeaboi-2.8.0/tests/unit/test_performance_roster.py +65 -0
  322. yeaboi-2.8.0/tests/unit/test_performance_screen.py +71 -0
  323. yeaboi-2.8.0/tests/unit/test_performance_store.py +98 -0
  324. yeaboi-2.8.0/tests/unit/test_provider_model_select.py +875 -0
  325. yeaboi-2.8.0/tests/unit/test_provider_verify_notion.py +60 -0
  326. yeaboi-2.8.0/tests/unit/test_questionnaire_io.py +279 -0
  327. yeaboi-2.8.0/tests/unit/test_reporting_activity.py +77 -0
  328. yeaboi-2.8.0/tests/unit/test_reporting_engine.py +188 -0
  329. yeaboi-2.8.0/tests/unit/test_reporting_export.py +68 -0
  330. yeaboi-2.8.0/tests/unit/test_reporting_presentation.py +76 -0
  331. yeaboi-2.8.0/tests/unit/test_reporting_screen.py +102 -0
  332. yeaboi-2.8.0/tests/unit/test_reporting_sprints.py +87 -0
  333. yeaboi-2.8.0/tests/unit/test_reporting_store.py +82 -0
  334. yeaboi-2.8.0/tests/unit/test_retro_board.py +314 -0
  335. yeaboi-2.8.0/tests/unit/test_retro_engine.py +112 -0
  336. yeaboi-2.8.0/tests/unit/test_retro_export.py +76 -0
  337. yeaboi-2.8.0/tests/unit/test_retro_page.py +144 -0
  338. yeaboi-2.8.0/tests/unit/test_retro_screen.py +82 -0
  339. yeaboi-2.8.0/tests/unit/test_retro_server.py +268 -0
  340. yeaboi-2.8.0/tests/unit/test_retro_store.py +78 -0
  341. yeaboi-2.8.0/tests/unit/test_retro_tunnel.py +104 -0
  342. yeaboi-2.8.0/tests/unit/test_setup_wizard.py +415 -0
  343. yeaboi-2.8.0/tests/unit/test_shared_components.py +447 -0
  344. yeaboi-2.8.0/tests/unit/test_standup_activity.py +208 -0
  345. yeaboi-2.8.0/tests/unit/test_standup_collector.py +150 -0
  346. yeaboi-2.8.0/tests/unit/test_standup_confidence.py +127 -0
  347. yeaboi-2.8.0/tests/unit/test_standup_delivery.py +189 -0
  348. yeaboi-2.8.0/tests/unit/test_standup_engine.py +248 -0
  349. yeaboi-2.8.0/tests/unit/test_standup_export.py +89 -0
  350. yeaboi-2.8.0/tests/unit/test_standup_interactive.py +91 -0
  351. yeaboi-2.8.0/tests/unit/test_standup_scheduler.py +182 -0
  352. yeaboi-2.8.0/tests/unit/test_standup_screen.py +180 -0
  353. yeaboi-2.8.0/tests/unit/test_standup_store.py +145 -0
  354. yeaboi-2.8.0/tests/unit/test_state.py +950 -0
  355. yeaboi-2.8.0/tests/unit/test_team_profile.py +1377 -0
  356. yeaboi-2.8.0/tests/unit/test_tips.py +137 -0
  357. yeaboi-2.8.0/tests/unit/test_tips_ui.py +44 -0
  358. yeaboi-2.8.0/tests/unit/test_token_budgets.py +308 -0
  359. yeaboi-2.8.0/tests/unit/test_ui_error_classification.py +115 -0
  360. yeaboi-2.8.0/tests/unit/test_voice.py +426 -0
  361. yeaboi-2.8.0/tests/unit/tools/__init__.py +0 -0
  362. yeaboi-2.8.0/tests/unit/tools/test_tools_azure_devops.py +620 -0
  363. yeaboi-2.8.0/tests/unit/tools/test_tools_calendar.py +258 -0
  364. yeaboi-2.8.0/tests/unit/tools/test_tools_codebase.py +367 -0
  365. yeaboi-2.8.0/tests/unit/tools/test_tools_confluence.py +515 -0
  366. yeaboi-2.8.0/tests/unit/tools/test_tools_github.py +477 -0
  367. yeaboi-2.8.0/tests/unit/tools/test_tools_jira.py +903 -0
  368. yeaboi-2.8.0/tests/unit/tools/test_tools_llm.py +296 -0
  369. yeaboi-2.8.0/tests/unit/tools/test_tools_notion.py +478 -0
  370. yeaboi-2.8.0/tests/unit/tools/test_tools_registry.py +165 -0
  371. yeaboi-2.8.0/tests/unit/tools/test_tools_team_learning.py +529 -0
  372. yeaboi-2.8.0/uv.lock +2650 -0
@@ -0,0 +1,126 @@
1
+ # LLM Provider
2
+ # Options: anthropic (default), openai, google
3
+ # Install additional providers: uv sync --extra openai or uv sync --extra google
4
+ LLM_PROVIDER=anthropic
5
+ # Optional: override the default model for the selected provider
6
+ # Anthropic default: claude-sonnet-4-20250514
7
+ # OpenAI default: gpt-4o
8
+ # Google default: gemini-2.0-flash
9
+ LLM_MODEL=
10
+
11
+ # Anthropic (required when LLM_PROVIDER=anthropic)
12
+ ANTHROPIC_API_KEY=your-anthropic-api-key
13
+
14
+ # OpenAI (required when LLM_PROVIDER=openai)
15
+ OPENAI_API_KEY=your-openai-api-key
16
+
17
+ # Google AI (required when LLM_PROVIDER=google)
18
+ GOOGLE_API_KEY=your-google-api-key
19
+
20
+ # LangSmith (optional — enables tracing for development)
21
+ LANGSMITH_TRACING=true
22
+ LANGSMITH_API_KEY=your-langsmith-api-key
23
+ LANGSMITH_PROJECT=yeaboi
24
+
25
+ # GitHub (optional — enables repo context tools; required for private repos and higher rate limits)
26
+ # Fine-grained PAT: Contents=Read, Issues=Read, Metadata=Read
27
+ # Classic PAT: public_repo (public repos) or repo (private repos)
28
+ # No token: works for public repos at 60 req/hour (unauthenticated)
29
+ GITHUB_TOKEN=your-github-personal-access-token
30
+
31
+ # Azure DevOps (optional — enables repo context tools and board sync; required for private projects)
32
+ # PAT permissions needed: Code=Read, Work Items=Read+Write, Project=Read
33
+ AZURE_DEVOPS_TOKEN=your-azure-devops-personal-access-token
34
+ # Organization URL (e.g. https://dev.azure.com/myorg) — required for board sync
35
+ AZURE_DEVOPS_ORG_URL=https://dev.azure.com/your-org
36
+ # Project name — required for board sync
37
+ AZURE_DEVOPS_PROJECT=MyProject
38
+ # Team name (optional — defaults to "{project} Team")
39
+ AZURE_DEVOPS_TEAM=
40
+
41
+ # Jira Cloud / Atlassian (optional — enables Jira board read + issue creation tools)
42
+ # API token: id.atlassian.com → Security → API tokens
43
+ # No trailing slash on JIRA_BASE_URL
44
+ JIRA_BASE_URL=https://your-org.atlassian.net
45
+ JIRA_EMAIL=you@example.com
46
+ JIRA_API_TOKEN=your-jira-api-token
47
+ JIRA_PROJECT_KEY=MYPROJ
48
+
49
+ # Team analysis (optional — extra API calls to improve “Repository activity”)
50
+ # Jira: fetch dev-status (linked PRs/branches from Jira Software Development panel)
51
+ #TEAM_ANALYSIS_JIRA_DEV_LINKS=true
52
+ # Azure DevOps: scan recent Git PRs for work item links / id in branch name (per-repo cap)
53
+ #TEAM_ANALYSIS_AZDO_BRANCH_SEARCH=true
54
+ #TEAM_ANALYSIS_AZDO_PR_SEARCH_MAX_REPOS=10
55
+ #TEAM_ANALYSIS_AZDO_PR_SEARCH_PRS_PER_REPO=75
56
+ #TEAM_ANALYSIS_AZDO_REPO_ALLOWLIST=my-repo,other-repo
57
+
58
+ # Confluence (optional — shares Atlassian auth with Jira; only space key is new)
59
+ # Space key is the short identifier visible in your Confluence space URL
60
+ CONFLUENCE_SPACE_KEY=MYSPACE
61
+
62
+ # Notion (optional — its own doc tool, independent of Jira/Confluence)
63
+ # Create an internal integration at https://www.notion.so/my-integrations, then
64
+ # share the pages/databases you want the agent to read with that integration.
65
+ NOTION_TOKEN=ntn_your-notion-integration-token
66
+ # Optional: a root page or database ID used as the default parent for created
67
+ # pages. Notion has no "space key"; search spans whatever the integration is granted.
68
+ NOTION_ROOT_PAGE_ID=
69
+
70
+ # Voice input (optional — double-tap Space in any text field to dictate)
71
+ # Transcription runs locally & offline via faster-whisper (works with ANY LLM
72
+ # provider, no API key). Install with: uv sync --extra voice
73
+ # (self-contained on macOS/Windows; Linux also needs: apt install libportaudio2).
74
+ # VOICE_MODEL is the local Whisper model size, not a cloud model name.
75
+ # Options: tiny, base (default), small, medium, large-v3 (+ .en variants).
76
+ # Larger = more accurate but slower and a bigger one-time download.
77
+ VOICE_MODEL=base
78
+
79
+ # On-screen tips
80
+ # Rotating discoverability tips on the welcome screen + inline voice hints.
81
+ # Default on; set to false to hide all tips. Toggle live by pressing "t" on the
82
+ # welcome screen (the choice is saved back here automatically).
83
+ TIPS_ENABLED=true
84
+
85
+ # Session management
86
+ # Auto-prune sessions older than N days (default 30, set to 0 to disable)
87
+ SESSION_PRUNE_DAYS=30
88
+
89
+ # Logging
90
+ # Controls the file logger at ~/.yeaboi/logs/tui/yeaboi.log
91
+ # Values: DEBUG, INFO, WARNING (default), ERROR
92
+ # Set to DEBUG to capture full diagnostics for troubleshooting
93
+ LOG_LEVEL=WARNING
94
+
95
+ # ── Daily Standup mode ─────────────────────────────────────────────────
96
+ # Detects team activity (Jira/AzDO/GitHub/Confluence/local git), computes
97
+ # sprint day + confidence, and delivers a daily summary. Schedule time and
98
+ # delivery-channel selection are configured per-project in the Daily Standup
99
+ # TUI page (stored in SQLite); the values below are the shared secrets/creds.
100
+ #
101
+ # Your display name for your own standup update (default: "Me")
102
+ # STANDUP_USER_NAME=Omar
103
+ #
104
+ # GitHub repo to scan for code activity (owner/repo or full URL)
105
+ # STANDUP_GITHUB_REPO=owner/repo
106
+ #
107
+ # Slack delivery — incoming webhook URL (https://api.slack.com/messaging/webhooks)
108
+ # SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz
109
+ #
110
+ # Email delivery — SMTP settings
111
+ # STANDUP_SMTP_HOST=smtp.gmail.com
112
+ # STANDUP_SMTP_PORT=587
113
+ # STANDUP_SMTP_USER=you@example.com
114
+ # STANDUP_SMTP_PASSWORD=your-app-password
115
+ # STANDUP_SMTP_SENDER=you@example.com
116
+ # STANDUP_EMAIL_RECIPIENTS=teammate1@example.com,teammate2@example.com
117
+
118
+ # ─── Retro mode ─────────────────────────────────────────────────────────────
119
+ # The Retro page starts a small LAN web server so teammates can add cards from a
120
+ # browser. Base port to bind (walks upward if busy). Default: 5173.
121
+ # RETRO_PORT=5173
122
+ #
123
+ # "Share Remotely" opens a public Cloudflare tunnel for off-network teammates.
124
+ # The app auto-downloads cloudflared to ~/.yeaboi/bin/ (no account needed).
125
+ # Set this only to point at an existing cloudflared binary instead.
126
+ # CLOUDFLARED_PATH=/usr/local/bin/cloudflared
@@ -0,0 +1,107 @@
1
+ name: Auto Version Bump
2
+
3
+ # Classify each PR and, for release-worthy changes, bump the version in
4
+ # pyproject.toml on the PR branch. Merging then triggers publish.yml (which
5
+ # releases whenever the version has no matching tag) — so releases happen with no
6
+ # manual version bump. Cheap deterministic guards run first; the LLM is only asked
7
+ # to choose the semver level when the change actually ships code.
8
+ #
9
+ # The bump lands on the PR *branch* (not main) on purpose: the human merge is what
10
+ # pushes to main and triggers publish.yml. A workflow pushing to main with the
11
+ # default GITHUB_TOKEN would NOT re-trigger publish.yml, so this avoids needing a PAT.
12
+ on:
13
+ pull_request:
14
+ types: [opened, synchronize, reopened, labeled]
15
+ branches: [main]
16
+
17
+ concurrency:
18
+ group: auto-version-${{ github.event.pull_request.number }}
19
+ cancel-in-progress: true
20
+
21
+ jobs:
22
+ bump:
23
+ name: Decide & apply version bump
24
+ # Same-repo PRs only (forks can't push to the head branch or read secrets).
25
+ if: >
26
+ github.event.pull_request.head.repo.full_name == github.repository &&
27
+ github.event.pull_request.state == 'open'
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ contents: write # commit the bump to the PR branch
31
+ pull-requests: write # post the explanation comment
32
+ id-token: write # claude-code-action OIDC
33
+ steps:
34
+ - name: Checkout PR branch
35
+ uses: actions/checkout@v4
36
+ with:
37
+ ref: ${{ github.event.pull_request.head.ref }}
38
+ fetch-depth: 0
39
+
40
+ - name: Deterministic guards
41
+ id: guard
42
+ env:
43
+ GH_TOKEN: ${{ github.token }}
44
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
45
+ PR: ${{ github.event.pull_request.number }}
46
+ LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }}
47
+ run: |
48
+ set -euo pipefail
49
+ ver() { sed -nE 's/^version = "([^"]+)".*/\1/p' | head -1; }
50
+ git fetch --no-tags origin "$BASE_REF"
51
+ BASE_V=$(git show "FETCH_HEAD:pyproject.toml" | ver)
52
+ HEAD_V=$(ver < pyproject.toml)
53
+ echo "base=$BASE_V head=$HEAD_V labels=[$LABELS]"
54
+
55
+ # 1) Already bumped in this PR (manual, or a prior auto run) -> skip.
56
+ # Keeps re-runs on `synchronize` idempotent and respects manual bumps.
57
+ if [ "$HEAD_V" != "$BASE_V" ]; then
58
+ echo "skip=true" >> "$GITHUB_OUTPUT"
59
+ echo "::notice::version already changed in this PR ($BASE_V -> $HEAD_V); skipping."
60
+ exit 0
61
+ fi
62
+
63
+ # 2) A semver:* / release:skip label forces the LLM step to run.
64
+ case ",$LABELS," in
65
+ *,semver:major,*|*,semver:minor,*|*,semver:patch,*|*,semver:none,*|*,release:skip,*)
66
+ echo "skip=false" >> "$GITHUB_OUTPUT"; exit 0 ;;
67
+ esac
68
+
69
+ # 3) Trivial PR? No shipping code changed -> skip (docs/chore/tests/CI only).
70
+ if gh pr diff "$PR" --name-only | grep -qE '^src/yeaboi/'; then
71
+ echo "skip=false" >> "$GITHUB_OUTPUT"
72
+ else
73
+ echo "skip=true" >> "$GITHUB_OUTPUT"
74
+ echo "::notice::no src/yeaboi changes; skipping version bump."
75
+ fi
76
+
77
+ - name: Classify & bump with Claude
78
+ if: steps.guard.outputs.skip == 'false'
79
+ uses: anthropics/claude-code-action@v1
80
+ with:
81
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
82
+ claude_args: '--allowedTools "Bash,Read,Edit,Write"'
83
+ prompt: |
84
+ You are the release-versioning bot for this repository. Pull request #${{ github.event.pull_request.number }} is open; decide whether and how to bump the project version. The version lives only in pyproject.toml.
85
+
86
+ Follow these steps exactly:
87
+
88
+ 1. Choose a semver level, in this priority order:
89
+ a. Labels win. If the PR has label `semver:major`, `semver:minor`, or `semver:patch`, use that level. If it has `release:skip` or `semver:none`, treat the level as "none".
90
+ b. Otherwise classify this PR's diff:
91
+ - "major": a backward-incompatible change (removed/renamed CLI flags, changed output formats, breaking behavior or public API).
92
+ - "minor": a new user-facing capability or feature.
93
+ - "patch": a bug fix, performance, or internal refactor with no new user-facing surface.
94
+ - "none": the diff only touches docs, comments, tests, or CI/workflow files.
95
+
96
+ 2. If the level is "none": do NOT modify any file. Post one short PR comment: "🏷️ auto-version: no release-worthy change — skipping bump." Then stop.
97
+
98
+ 3. Otherwise run exactly this command (it rewrites pyproject.toml and prints the NEW version):
99
+ python scripts/bump_version.py <level>
100
+ Commit ONLY the pyproject.toml change to this PR branch and push it. Use commit message:
101
+ chore: bump version to <new-version> [auto]
102
+ with trailer:
103
+ Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
104
+
105
+ 4. Post one short PR comment naming the level, the new version, and a one-sentence reason.
106
+
107
+ Rules: only ever edit pyproject.toml; never bump more than once; keep the comment to one or two lines.
@@ -0,0 +1,79 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ # Least-privilege token — these jobs only check out code and run tests.
10
+ permissions:
11
+ contents: read
12
+
13
+ # Cancel in-progress runs on the same branch when a new push arrives.
14
+ concurrency:
15
+ group: ${{ github.workflow }}-${{ github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ # ── Fast gate ────────────────────────────────────────────────────────────
20
+ # Unit tests — also enforced locally by the pre-commit hook in
21
+ # .pre-commit-config.yaml. Running them in CI too catches contributors
22
+ # who haven't installed pre-commit.
23
+ unit:
24
+ name: Unit tests
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: astral-sh/setup-uv@v4
29
+ - run: uv python install 3.11
30
+ - run: uv sync --extra dev
31
+ - run: make test-fast
32
+
33
+ # ── Slow suite ───────────────────────────────────────────────────────────
34
+ # Integration + contract tests (marked @pytest.mark.slow) — too slow for
35
+ # pre-commit but must pass before any PR merges. All external calls are
36
+ # mocked or VCR-replayed; no real API keys required.
37
+ integration:
38
+ name: Integration & contract tests
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - uses: astral-sh/setup-uv@v4
43
+ - run: uv python install 3.11
44
+ - run: uv sync --extra dev
45
+ - run: make test
46
+
47
+ # ── Golden evaluators ────────────────────────────────────────────────────
48
+ # LLM-output quality checks against the golden dataset.
49
+ # Kept separate so a quality regression doesn't block unrelated PRs.
50
+ eval:
51
+ name: Golden evaluators
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - uses: astral-sh/setup-uv@v4
56
+ - run: uv python install 3.11
57
+ - run: uv sync --extra dev
58
+ - run: make eval
59
+
60
+ # ── Code quality ─────────────────────────────────────────────────────────
61
+ lint:
62
+ name: Lint (ruff)
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+ - uses: astral-sh/setup-uv@v4
67
+ - run: uv python install 3.11
68
+ - run: uv sync --extra dev
69
+ - run: make lint
70
+
71
+ format-check:
72
+ name: Format check (ruff)
73
+ runs-on: ubuntu-latest
74
+ steps:
75
+ - uses: actions/checkout@v4
76
+ - uses: astral-sh/setup-uv@v4
77
+ - run: uv python install 3.11
78
+ - run: uv sync --extra dev
79
+ - run: uv run ruff format --check src/ tests/
@@ -0,0 +1,48 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, ready_for_review, reopened]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@v1
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+ # Allow bot-initiated runs: auto-version.yml pushes a `chore: bump version`
40
+ # commit authored by the `claude` bot, whose `synchronize` event would
41
+ # otherwise be rejected ("Workflow initiated by non-human actor"). '*'
42
+ # permits any bot; narrow to 'claude' if you want only the version bumper.
43
+ allowed_bots: '*'
44
+ plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
45
+ plugins: 'code-review@claude-code-plugins'
46
+ prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://code.claude.com/docs/en/cli-reference for available options
@@ -0,0 +1,49 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@v1
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44
+ # prompt: 'Update the pull request description to include a summary of changes.'
45
+
46
+ # Optional: Add claude_args to customize behavior and configuration
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://code.claude.com/docs/en/cli-reference for available options
49
+ # claude_args: '--allowed-tools Bash(gh pr:*)'
@@ -0,0 +1,86 @@
1
+ name: Publish to PyPI
2
+
3
+ # Auto-release on version bump. On every push to main, publish to PyPI *iff* the
4
+ # version in pyproject.toml has no matching git tag yet. So releasing is just:
5
+ # bump `version` in pyproject.toml and merge to main — CI publishes, tags, and
6
+ # cuts a GitHub Release. Normal merges (version unchanged) are a cheap no-op.
7
+ #
8
+ # The workflow filename MUST stay "publish.yml" to keep PyPI's OIDC trusted-
9
+ # publisher configuration valid.
10
+ on:
11
+ push:
12
+ branches: [main]
13
+ workflow_dispatch: {} # allow a manual re-run from the Actions tab
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ check:
20
+ name: Check for version bump
21
+ runs-on: ubuntu-latest
22
+ outputs:
23
+ should_release: ${{ steps.v.outputs.should_release }}
24
+ version: ${{ steps.v.outputs.version }}
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ with:
28
+ fetch-depth: 0 # need full history + tags to check for an existing release
29
+ - id: v
30
+ run: |
31
+ VERSION=$(grep -m1 -E '^version = ' pyproject.toml | sed -E 's/^version = "([^"]+)".*/\1/')
32
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
33
+ if git rev-parse -q --verify "refs/tags/v$VERSION" >/dev/null; then
34
+ echo "should_release=false" >> "$GITHUB_OUTPUT"
35
+ echo "::notice::v$VERSION is already released — nothing to publish."
36
+ else
37
+ echo "should_release=true" >> "$GITHUB_OUTPUT"
38
+ echo "::notice::New version v$VERSION detected — building and publishing."
39
+ fi
40
+
41
+ test:
42
+ name: Lint & Test
43
+ needs: check
44
+ if: needs.check.outputs.should_release == 'true'
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ - uses: astral-sh/setup-uv@v4
49
+ - run: uv python install 3.12
50
+ - run: uv sync --extra dev
51
+ - run: make lint
52
+ - run: make test
53
+
54
+ publish:
55
+ name: Build & Publish to PyPI
56
+ needs: [check, test]
57
+ if: needs.check.outputs.should_release == 'true'
58
+ runs-on: ubuntu-latest
59
+ environment: pypi
60
+ permissions:
61
+ id-token: write # PyPI trusted publishing (OIDC)
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+ - uses: astral-sh/setup-uv@v4
65
+ - run: uv python install 3.12
66
+ - run: uv build
67
+ - name: Publish to PyPI
68
+ uses: pypa/gh-action-pypi-publish@release/v1
69
+ with:
70
+ skip-existing: true # idempotent: re-runs won't fail if already published
71
+
72
+ release:
73
+ name: Tag & GitHub Release
74
+ needs: [check, publish]
75
+ if: needs.check.outputs.should_release == 'true'
76
+ runs-on: ubuntu-latest
77
+ permissions:
78
+ contents: write # create the tag + GitHub Release
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+ - name: Create tag and GitHub Release
82
+ uses: softprops/action-gh-release@v2
83
+ with:
84
+ tag_name: v${{ needs.check.outputs.version }}
85
+ name: v${{ needs.check.outputs.version }}
86
+ generate_release_notes: true
@@ -0,0 +1,44 @@
1
+ name: Smoke Tests
2
+
3
+ on:
4
+ schedule:
5
+ # Every Monday at 06:00 UTC
6
+ - cron: "0 6 * * 1"
7
+ workflow_dispatch: # Allow manual trigger from GitHub UI
8
+
9
+ # Least-privilege token — this job only checks out code and runs tests.
10
+ # Real API credentials are injected via repository secrets, not GITHUB_TOKEN.
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ smoke:
16
+ if: false # Disabled — re-enable when secrets are configured
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: astral-sh/setup-uv@v4
21
+ - run: uv python install 3.11
22
+ - run: uv sync --extra dev --extra all-providers
23
+
24
+ - name: Run smoke tests
25
+ env:
26
+ # Jira / Confluence
27
+ JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
28
+ JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
29
+ JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
30
+ JIRA_PROJECT_KEY: ${{ secrets.JIRA_PROJECT_KEY }}
31
+ CONFLUENCE_SPACE_KEY: ${{ secrets.CONFLUENCE_SPACE_KEY }}
32
+ # SMOKE_GITHUB_TOKEN: a PAT for broader GitHub access (cross-org calls etc.)
33
+ # GITHUB_BUILTIN_TOKEN: always has contents:read for this repo; used as
34
+ # a runtime fallback in conftest.py when the PAT returns 404.
35
+ GITHUB_TOKEN: ${{ secrets.SMOKE_GITHUB_TOKEN }}
36
+ GITHUB_BUILTIN_TOKEN: ${{ github.token }}
37
+ # Azure DevOps
38
+ AZURE_DEVOPS_TOKEN: ${{ secrets.AZURE_DEVOPS_TOKEN }}
39
+ AZURE_DEVOPS_SMOKE_REPO_URL: ${{ secrets.AZURE_DEVOPS_SMOKE_REPO_URL }}
40
+ # LLM providers
41
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
42
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
43
+ GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
44
+ run: make smoke-test
@@ -0,0 +1,62 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ eggs/
11
+ *.whl
12
+ .eggs/
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+ ENV/
19
+
20
+ # Environment variables
21
+ .env
22
+ .env.local
23
+ .env.*.local
24
+
25
+ # IDE
26
+ .vscode/
27
+ .idea/
28
+ *.swp
29
+ *.swo
30
+ *~
31
+ .DS_Store
32
+
33
+ # Testing
34
+ .pytest_cache/
35
+ .coverage
36
+ htmlcov/
37
+ .tox/
38
+
39
+ # Vector store
40
+ chroma_db/
41
+
42
+ # LangSmith / LangChain
43
+ .langsmith/
44
+
45
+ # Distribution
46
+ *.tar.gz
47
+ *.zip
48
+
49
+ # Jupyter
50
+ .ipynb_checkpoints/
51
+
52
+ # Generated output
53
+ scrum-plan.*
54
+ scrum-questionnaire.md
55
+
56
+ # References
57
+ Capacity_Plan_Template.xlsx
58
+ SCRUM.md
59
+
60
+ # Allow test fixtures (overrides SCRUM.md ignore above)
61
+ !tests/fixtures/SCRUM.md
62
+ !projects/*/SCRUM.md
@@ -0,0 +1,29 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ exclude: \.ambr$
7
+ - id: end-of-file-fixer
8
+ - id: check-yaml
9
+ - id: check-added-large-files
10
+ exclude: ^docs/
11
+ - id: check-merge-conflict
12
+
13
+ - repo: https://github.com/astral-sh/ruff-pre-commit
14
+ rev: v0.15.2
15
+ hooks:
16
+ - id: ruff
17
+ args: [--fix]
18
+ - id: ruff-format
19
+
20
+ # Run unit tests before every commit (< 3s, no API keys, no graph compilation).
21
+ # Integration + contract tests run in CI on every PR — see .github/workflows/ci.yml.
22
+ - repo: local
23
+ hooks:
24
+ - id: unit-tests
25
+ name: Unit tests
26
+ language: system
27
+ entry: uv run pytest tests/unit/ --tb=short -q
28
+ pass_filenames: false
29
+ files: \.py$