System Architecture
Code Mint automates Jira-to-PR workflow using Claude CLI for AI-powered code generation.
┌─────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────┐
│ Jira │───>│ Webhook │───>│ Orchestrator │───>│ Claude │
│ Webhook │ │ Server │ │ │ │ CLI │
└─────────┘ └──────────────┘ └──────┬──────┘ └────┬─────┘
│ │
┌──────┴──────┐ ┌─────┴─────┐
│ Context │ │ Git Manager│
│ Gatherer │ │ + Bitbucket│
└──────────────┘ └────────────┘
Processing Pipeline
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ WEBHOOK │────>│ CONTEXT │────>│ CLARIFY │────>│ CLONE │────>│ CODEGEN │
│ receive │ │ gather │ │ (if need)│ │ repo │ │ Claude │
└─────────┘ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘
│
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ LEARN │<────│ JIRA │<────│ PR │<────│ VALIDATE │<─────────┘
│ record │ │ comment │ │ create │ │ test/lint│
└─────────┘ └──────────┘ └──────────┘ └──────────┘
~50ms | 2-5s | 1-2min | 2-30s | 2-8min | 10s-2min | 1-2s | 500ms | 50ms
Module Reference
| Module | Purpose |
|---|---|
| webhook_server.py | FastAPI server, webhook handlers (Jira + Bitbucket) |
| orchestrator.py | Main process_ticket() coordination |
| context_gatherer.py | Enrich tickets with epic, links, comments |
| learning_store.py | Record implementations, find similar tickets |
| db.py | PostgreSQL ORM models and store |
| postgres_store.py | Optional PostgreSQL store for metadata |
| repo_router.py | Determine target repositories |
| plan_store.py | Manage pending implementation plans |
| agent.py | Plan extraction, session reading, Claude API fallback |
| git_utils.py | Git clone, branch, commit, push |
| bitbucket_client.py | Bitbucket PR creation |
| jira_client.py | Jira API operations |
| config.py | Configuration loading and validation |
| models.py | Pydantic models for all data structures |
| prompts.py | All prompts for Claude interactions |
Work Directory Structure
~/.jira-automation/ ├── webhook_logs/ # Incoming webhook payloads │ └── {TIMESTAMP}_{KEY}_{EVENT}.json ├── jobs/ # Job metadata (Postgres primary) │ └── {TICKET-ID}.json ├── plans/ # Implementation plans │ └── {TICKET-ID}_v{N}.md ├── job_logs/ # Per-job log files │ └── {JOB-ID}.log ├── learning/ # Continuous learning │ ├── index.jsonl # Grep-searchable index │ └── records/ │ ├── {TICKET}.json # Structured record │ └── {TICKET}/ │ └── outcome.md # Agent-readable markdown ├── {repo}/ # Main clone (shared) └── {repo}-worktrees/ # Per-ticket isolation └── {TICKET}/
Integration Architecture
Jira REST API (Basic Auth)
GET /issue/{id}— Epic, linksGET /issue/{id}/comment— CommentsGET /issue/{id}/remotelink— Confluence/FigmaPOST /issue/{id}/comment— Post resultsPUT /issue/{id}— Add labels
Bitbucket REST API (Bearer token)
POST /pullrequests— Create PRGET /pullrequests?q=— Find existinggit clone/push— HTTPS Basic Auth
Claude CLI (OAuth)
--permission-mode plan— Read-only phases--dangerously-skip-permissions— Code gen--resume {id}— Session continuity--add-dir— Learning, context, repos
Confluence (Basic Auth, optional)
GET /content/{id}— Fetch page body
Concurrency & Isolation
Worktree Strategy
Main Clone ({repo}/.git)
├── git worktree add ──> {repo}-worktrees/PROJ-123/
├── git worktree add ──> {repo}-worktrees/PROJ-456/
└── git worktree add ──> {repo}-worktrees/PROJ-789/
Deduplication Flow
Webhook ──> Auto-code label? ──NO──> Reject (skip cache) │ YES │ PostgreSQL? ──YES──> try_acquire_lock (10s) │ │ NO ┌─────┴─────┐ │ acquired not acquired In-memory cache │ │ (10s window) Running? SKIP: dup │ │ │ unique duplicate ┌────┴────┐ │ │ YES NO Running? SKIP SKIP Continue
Learning Feedback Loop
┌─ Code Generation ───────────────────┐
│ Prompt Builder ──> Claude CLI │
│ ↑ │ │
│ Agent searches │ │
│ learning/ via grep ↓ │
└─────────────────> PR + Output ─┘
│
↓
┌─ Learning Store ────────┐
│ JSON Record │
│ outcome.md │
│ index.jsonl ─────────│──> grep similar ──> next generation
└───────────────────────┘
How agents use learnings:
- Learning directory injected via
--add-dir learning/ - Agent runs
grep "payment" learning/index.jsonl - Agent reads
cat learning/records/PROJ-123/outcome.md - Past patterns inform current code generation
Architecture Decisions
Single Session over Parallel Subagents
Replaced multiple parallel Claude subagents with single-session processing.
> "Complexity is not sophistication."
Agent-Searchable Files over Pre-Injected Context
Mount directories via --add-dir instead of classifying and pre-injecting context.
> "Give agents tools instead of pre-chewing their food."
JSON Structured Output over Marker Parsing
Switched from regex-parsed
### FILE: markers to CodeGenOutput JSON.> "Parse only what the system needs for routing."
Independent Review over Self-Review
Separate read-only Claude session with no memory of generation.
> "Verification must be structurally independent from creation."
LLM-Powered Clarification over Static Rules
LLM reasons about the ticket in context of the target repo.
> "If the decision requires judgment, use a model that can exercise judgment."
Centralized Prompts over Scattered Strings
All prompts in prompts.py. Single source of truth.
> "Prompts are code. Treat them with the same discipline."
Multi-Tag Classification over Single Enum
LLM generates
tags: list[str] instead of single classification.> "Don't force false choices in classification."
PostgreSQL with JSON Fallback
PostgreSQL as primary for row-level dedup locking. JSON files as fallback.
> "Build for the deployment model you're heading toward."
Git Worktrees for Isolation
Each ticket gets an isolated worktree from a shared main clone.
> "Filesystem isolation beats branch-based isolation."
Design Principles
01.
Remove logic, add tools — Strip orchestrator-driven decision-making.
02.
Agent-searchable over pre-injected — Mount files, don't stuff prompts.
03.
Single code path — One flow for single-repo and multi-repo.
04.
Fail open, log everything — Non-critical failures log warnings.
05.
Structural independence — Verification separate from creation.
06.
Session continuity — One conversation per ticket.
07.
File-based simplicity — Raw markdown, JSONL, JSON. No custom formats.