Development
Commands
make install # install uv + dependencies
make test # unit + integration + contract tests (full suite)
make test-fast # unit tests only (< 3s)
make test-v # full suite verbose
make test-all # everything including golden evaluators
make lint # lint with ruff
make format # format with ruff
make run # run the CLI (ARGS="--flag")
make run-dry # TUI with fake delays, no LLM calls
make eval # golden dataset evaluators
make contract # contract tests (recorded API responses)
make smoke-test # live API smoke tests (requires credentials)
make snapshot-update # update syrupy snapshot baselines
make budget-report # show prompt token counts
make graph # generate agent graph PNG
make build # build sdist + wheel into dist/
make publish # publish to PyPI
make clean # remove build artifacts and caches
Project Structure
src/yeaboi/
├── agent/ # LangGraph state & graph
│ ├── graph.py # Graph compilation & wiring
│ ├── llm.py # LLM provider selection (Anthropic/OpenAI/Google)
│ ├── nodes.py # Node functions (intake, analyze, generate, etc.)
│ └── state.py # ScrumState, QuestionnaireState, artifact dataclasses
├── prompts/ # Prompt templates per node
│ ├── analyzer.py # Project analyzer prompt
│ ├── feature_generator.py # Feature generation prompt
│ ├── intake.py # 30 questions, smart/standard modes, adaptive templates
│ ├── sprint_planner.py # Sprint planning prompt
│ ├── story_writer.py # Story writing prompt with few-shot examples
│ ├── system.py # Base system prompt
│ └── task_decomposer.py # Task decomposition prompt
├── tools/ # Tool definitions (23 total)
│ ├── azure_devops.py # Azure DevOps repo/file/work items
│ ├── calendar_tools.py # Bank holiday detection
│ ├── codebase.py # Local repo scanning
│ ├── confluence.py # Confluence search/read/write
│ ├── notion.py # Notion search/read/write (own token)
│ ├── github.py # GitHub repo/file/issues/readme
│ ├── jira.py # Jira board/velocity/sprint/epic/story
│ └── llm_tools.py # LLM-powered estimation and AC generation
├── ui/ # Full-screen TUI system
│ ├── mode_select/ # Mode selection screens
│ ├── provider_select/ # LLM/tool provider setup
│ ├── session/ # Main session (phases, editor, pipeline)
│ ├── shared/ # Animations, ASCII font, components, input
│ └── splash.py # Animated intro
├── repl/ # Legacy REPL (CLI-flag-driven flows)
│ ├── _intake_menu.py # Intake mode selection
│ ├── _io.py # Artifact rendering, file import/export
│ ├── _questionnaire.py # Questionnaire UI (one-at-a-time flow)
│ ├── _review.py # Review checkpoint UI
│ └── _ui.py # Pipeline progress, streaming, spinner
├── cli.py # CLI entry point (argparse, 20 flags)
├── config.py # Environment/config management
├── setup_wizard.py # First-run credential flow
├── sessions.py # SQLite session store
├── persistence.py # State serialization helpers
├── formatters.py # Rich rendering (dark/light themes)
├── input_guardrails.py # 4-layer input validation
├── output_guardrails.py # 4-layer output validation
├── questionnaire_io.py # Markdown questionnaire import/export
├── html_exporter.py # Self-contained HTML reports
├── json_exporter.py # JSON export for CI/CD
├── jira_sync.py # Batch Jira creation with idempotency
└── __init__.py # Version, LangSmith noise suppression
Testing Conventions
- One test file per source module:
repl.py → test_repl.py, state.py → test_state.py
- Group related tests in classes:
TestGracefulExit, TestStreaming, TestPriority
- Node tests live in
tests/unit/nodes/ (split into 9 files)
- Shared node test helpers in
tests/_node_helpers.py
- Pytest markers:
slow, eval, vcr, smoke
Environment Variables
| Variable | Required | Description |
ANTHROPIC_API_KEY | Yes (if using Anthropic) | Claude API key |
OPENAI_API_KEY | If using OpenAI | GPT API key |
GOOGLE_API_KEY | If using Google | Gemini API key |
LLM_PROVIDER | No | Provider selection: anthropic (default), openai, google |
GITHUB_TOKEN | No | GitHub PAT for repo context tools |
AZURE_DEVOPS_TOKEN | No | Azure DevOps PAT (Code=Read, Work Items=Read+Write, Project=Read) |
AZURE_DEVOPS_ORG_URL | If using AzDO Boards | Organization URL (e.g. https://dev.azure.com/myorg) |
AZURE_DEVOPS_PROJECT | If using AzDO Boards | Project name |
AZURE_DEVOPS_TEAM | No | Team name (defaults to {project} Team) |
JIRA_BASE_URL | If using Jira | Jira Cloud URL (e.g. https://org.atlassian.net) |
JIRA_EMAIL | If using Jira | Atlassian account email |
JIRA_API_TOKEN | If using Jira | Jira API token |
JIRA_PROJECT_KEY | If using Jira | Project key (e.g. MYPROJ) |
CONFLUENCE_SPACE_KEY | No | Confluence space key (shares Atlassian auth with Jira); Export buttons publish here |
CONFLUENCE_EXPORT_PARENT_PAGE_ID | No | Optional page Confluence exports nest under (blank = grouped under an auto-created 🤙 yeaboi page) |
NOTION_TOKEN | No | Notion integration token (its own auth; enables Notion doc tools) |
NOTION_ROOT_PAGE_ID | No | Default parent for created Notion pages; enables the Notion standup source; Notion exports fall back here |
NOTION_EXPORT_PARENT_PAGE_ID | No | Optional dedicated page the Export buttons publish under (blank = grouped under an auto-created 🤙 yeaboi page in NOTION_ROOT_PAGE_ID) |
YEABOI_HOME | No | Data home for everything yeaboi writes — exports, logs, sessions DB (default: ~/.yeaboi; .env always stays at ~/.yeaboi/.env; editable in Settings → Data Dir) |
LANGSMITH_TRACING | No | Enable LangSmith tracing (true) |
LANGSMITH_API_KEY | No | LangSmith API key |
LANGSMITH_PROJECT | No | LangSmith project name |
LOG_LEVEL | No | File-based log level: DEBUG/INFO/WARNING/ERROR (default: WARNING; also cyclable live from the Settings page) |
SESSION_PRUNE_DAYS | No | Auto-prune sessions older than N days (default: 30, 0=disabled) |
Git Conventions
- Commit messages: lowercase imperative (e.g., "add streaming output", "fix import sorting")
- Branch naming:
feature/<description> for feature work
- PRs: feature branches merge to
main via pull request
- Include
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> on AI-assisted commits
Evaluation & Testing
| Layer | Approach |
| Unit Tests | Prompt formatting, tool input/output validation, state transitions, artifact immutability |
| Integration Tests | CLI argument parsing, graph compilation, multi-node flows, session persistence |
| Contract Tests | VCR cassettes for GitHub, Jira, Confluence, Notion API responses |
| Golden Datasets | Curated project descriptions with expected feature/story breakdowns |
| Smoke Tests | Live API tests (require real credentials) |
| Token Budget Tests | Monitor prompt token counts for trend analysis |
| Red Teaming | Vague inputs, contradictory requirements, prompt injection, absurdly large scope |
Red Teaming Checklist
- Prompt injection ("Ignore your instructions and...")
- Jailbreaking (roleplay scenarios to bypass safety)
- Messy inputs (typos, slang, code-switching)
- Extremely long or empty project descriptions
- Contradictory requirements
- Adversarial inputs designed to trigger hallucination or bias
Graceful Degradation
| Failure Type | Strategy |
| API rate limit | Exponential backoff with live countdown (5s → 10s → 20s, 3 retries) |
| Tool call failure | Error displayed, pipeline continues |
| Model unavailable | Fallback to alternative provider (if configured) |
| Corrupt session | Returns (None, None) — no crash, user informed |
Tech Stack
| Component | Choice |
| Language | Python 3.11+ |
| Package Manager | uv |
| Agent Framework | LangGraph + LangChain |
| LLM | Anthropic Claude (primary), OpenAI GPT, Google Gemini |
| Terminal UI | rich + prompt_toolkit |
| Jira Integration | jira + atlassian-python-api |
| GitHub Integration | PyGithub |
| Azure DevOps | azure-devops SDK |
| Session Store | SQLite (via langgraph-checkpoint-sqlite) |
| Holiday Detection | holidays library |
| Linting | ruff (line-length 120) |
| Testing | pytest, pytest-asyncio, pytest-recording (VCR), syrupy (snapshots) |
| Observability | LangSmith |
For contributor workflow — worktrees, hooks, CI conventions — see CLAUDE.md in the repo root.