polycoding 0.1.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.
- polycoding-0.1.0/.dockerignore +80 -0
- polycoding-0.1.0/.env.example +104 -0
- polycoding-0.1.0/.gitignore +59 -0
- polycoding-0.1.0/AGENTS.md +299 -0
- polycoding-0.1.0/Dockerfile +39 -0
- polycoding-0.1.0/LICENSE +20 -0
- polycoding-0.1.0/Makefile +9 -0
- polycoding-0.1.0/PKG-INFO +225 -0
- polycoding-0.1.0/README.md +183 -0
- polycoding-0.1.0/docs/ARCHITECTURE.md +438 -0
- polycoding-0.1.0/docs/CELERY_README.md +333 -0
- polycoding-0.1.0/docs/CLI_USAGE.md +330 -0
- polycoding-0.1.0/docs/FLOWS.md +493 -0
- polycoding-0.1.0/docs/HOOK_ARCHITECTURE.md +330 -0
- polycoding-0.1.0/docs/PLUGIN.md +1274 -0
- polycoding-0.1.0/docs/QUICKSTART.md +184 -0
- polycoding-0.1.0/entrypooint.sh +47 -0
- polycoding-0.1.0/pyproject.toml +97 -0
- polycoding-0.1.0/src/AGENTS.md +1071 -0
- polycoding-0.1.0/src/README.md +99 -0
- polycoding-0.1.0/src/bootstrap.py +121 -0
- polycoding-0.1.0/src/channels/__init__.py +66 -0
- polycoding-0.1.0/src/channels/base.py +50 -0
- polycoding-0.1.0/src/channels/dispatcher.py +162 -0
- polycoding-0.1.0/src/channels/hooks.py +154 -0
- polycoding-0.1.0/src/channels/redis/__init__.py +37 -0
- polycoding-0.1.0/src/channels/redis/channel.py +109 -0
- polycoding-0.1.0/src/channels/stream/__init__.py +6 -0
- polycoding-0.1.0/src/channels/stream/config.py +19 -0
- polycoding-0.1.0/src/channels/stream/server.py +162 -0
- polycoding-0.1.0/src/channels/stream/server_app.py +62 -0
- polycoding-0.1.0/src/channels/types.py +63 -0
- polycoding-0.1.0/src/cli/__init__.py +53 -0
- polycoding-0.1.0/src/cli/db.py +67 -0
- polycoding-0.1.0/src/cli/flow.py +187 -0
- polycoding-0.1.0/src/cli/main.py +44 -0
- polycoding-0.1.0/src/cli/project.py +166 -0
- polycoding-0.1.0/src/cli/server.py +127 -0
- polycoding-0.1.0/src/cli/utils.py +70 -0
- polycoding-0.1.0/src/cli/worker.py +124 -0
- polycoding-0.1.0/src/crews/__init__.py +34 -0
- polycoding-0.1.0/src/crews/base.py +86 -0
- polycoding-0.1.0/src/crews/conversation_crew/__init__.py +6 -0
- polycoding-0.1.0/src/crews/conversation_crew/config/agents.yaml +20 -0
- polycoding-0.1.0/src/crews/conversation_crew/config/tasks.yaml +66 -0
- polycoding-0.1.0/src/crews/conversation_crew/conversation_crew.py +60 -0
- polycoding-0.1.0/src/crews/conversation_crew/types.py +11 -0
- polycoding-0.1.0/src/crews/implement_crew/__init__.py +4 -0
- polycoding-0.1.0/src/crews/implement_crew/config/agents.yaml +25 -0
- polycoding-0.1.0/src/crews/implement_crew/config/tasks.yaml +205 -0
- polycoding-0.1.0/src/crews/implement_crew/implement_crew.py +161 -0
- polycoding-0.1.0/src/crews/implement_crew/types.py +24 -0
- polycoding-0.1.0/src/crews/plan_crew/__init__.py +4 -0
- polycoding-0.1.0/src/crews/plan_crew/config/agents.yaml +30 -0
- polycoding-0.1.0/src/crews/plan_crew/config/tasks.yaml +78 -0
- polycoding-0.1.0/src/crews/plan_crew/plan_crew.py +80 -0
- polycoding-0.1.0/src/crews/plan_crew/types.py +36 -0
- polycoding-0.1.0/src/crews/ralph_crew/__init__.py +4 -0
- polycoding-0.1.0/src/crews/ralph_crew/config/agents.yaml +20 -0
- polycoding-0.1.0/src/crews/ralph_crew/config/tasks.yaml +55 -0
- polycoding-0.1.0/src/crews/ralph_crew/ralph_crew.py +77 -0
- polycoding-0.1.0/src/crews/ralph_crew/types.py +8 -0
- polycoding-0.1.0/src/crews/review_crew/__init__.py +4 -0
- polycoding-0.1.0/src/crews/review_crew/config/agents.yaml +9 -0
- polycoding-0.1.0/src/crews/review_crew/config/tasks.yaml +23 -0
- polycoding-0.1.0/src/crews/review_crew/review_crew.py +46 -0
- polycoding-0.1.0/src/crews/review_crew/types.py +11 -0
- polycoding-0.1.0/src/crews/streaming/__init__.py +19 -0
- polycoding-0.1.0/src/crews/streaming/callback.py +103 -0
- polycoding-0.1.0/src/crews/streaming/factory.py +49 -0
- polycoding-0.1.0/src/crews/streaming/publisher.py +100 -0
- polycoding-0.1.0/src/crews/streaming/types.py +45 -0
- polycoding-0.1.0/src/crews/test_crew/__init__.py +4 -0
- polycoding-0.1.0/src/crews/test_crew/config/agents.yaml +9 -0
- polycoding-0.1.0/src/crews/test_crew/config/tasks.yaml +28 -0
- polycoding-0.1.0/src/crews/test_crew/test_crew.py +49 -0
- polycoding-0.1.0/src/crews/test_crew/types.py +11 -0
- polycoding-0.1.0/src/crews/verify_crew/__init__.py +4 -0
- polycoding-0.1.0/src/crews/verify_crew/config/agents.yaml +9 -0
- polycoding-0.1.0/src/crews/verify_crew/config/tasks.yaml +30 -0
- polycoding-0.1.0/src/crews/verify_crew/types.py +11 -0
- polycoding-0.1.0/src/crews/verify_crew/verify_crew.py +49 -0
- polycoding-0.1.0/src/flows/__init__.py +15 -0
- polycoding-0.1.0/src/flows/base.py +245 -0
- polycoding-0.1.0/src/flows/protocol.py +30 -0
- polycoding-0.1.0/src/flows/ralph/__init__.py +13 -0
- polycoding-0.1.0/src/flows/ralph/flow.py +232 -0
- polycoding-0.1.0/src/flows/ralph/module.py +41 -0
- polycoding-0.1.0/src/flows/ralph/types.py +16 -0
- polycoding-0.1.0/src/flows/registry.py +124 -0
- polycoding-0.1.0/src/gitcore/__init__.py +38 -0
- polycoding-0.1.0/src/gitcore/hooks.py +94 -0
- polycoding-0.1.0/src/gitcore/module.py +56 -0
- polycoding-0.1.0/src/gitcore/operations.py +346 -0
- polycoding-0.1.0/src/gitcore/types.py +73 -0
- polycoding-0.1.0/src/github_app/__init__.py +13 -0
- polycoding-0.1.0/src/github_app/app.py +224 -0
- polycoding-0.1.0/src/github_app/auth.py +137 -0
- polycoding-0.1.0/src/github_app/config.py +38 -0
- polycoding-0.1.0/src/github_app/installation_manager.py +194 -0
- polycoding-0.1.0/src/github_app/label_mapper.py +112 -0
- polycoding-0.1.0/src/github_app/models.py +112 -0
- polycoding-0.1.0/src/github_app/webhook_handler.py +217 -0
- polycoding-0.1.0/src/glm.py +100 -0
- polycoding-0.1.0/src/modules/README.md +850 -0
- polycoding-0.1.0/src/modules/__init__.py +29 -0
- polycoding-0.1.0/src/modules/channels.py +109 -0
- polycoding-0.1.0/src/modules/context.py +31 -0
- polycoding-0.1.0/src/modules/hooks.py +101 -0
- polycoding-0.1.0/src/modules/protocol.py +92 -0
- polycoding-0.1.0/src/modules/registry.py +165 -0
- polycoding-0.1.0/src/modules/tasks.py +123 -0
- polycoding-0.1.0/src/persistence/__init__.py +5 -0
- polycoding-0.1.0/src/persistence/config.py +12 -0
- polycoding-0.1.0/src/persistence/postgres.py +346 -0
- polycoding-0.1.0/src/persistence/registry.py +111 -0
- polycoding-0.1.0/src/persistence/tasks.py +178 -0
- polycoding-0.1.0/src/project_manager/README.md +668 -0
- polycoding-0.1.0/src/project_manager/__init__.py +29 -0
- polycoding-0.1.0/src/project_manager/base.py +202 -0
- polycoding-0.1.0/src/project_manager/config.py +36 -0
- polycoding-0.1.0/src/project_manager/conversation/__init__.py +19 -0
- polycoding-0.1.0/src/project_manager/conversation/flow.py +233 -0
- polycoding-0.1.0/src/project_manager/conversation/types.py +64 -0
- polycoding-0.1.0/src/project_manager/flow_runner.py +160 -0
- polycoding-0.1.0/src/project_manager/git_utils.py +30 -0
- polycoding-0.1.0/src/project_manager/github.py +367 -0
- polycoding-0.1.0/src/project_manager/github_conversation.py +144 -0
- polycoding-0.1.0/src/project_manager/github_projects_client.py +329 -0
- polycoding-0.1.0/src/project_manager/hooks.py +377 -0
- polycoding-0.1.0/src/project_manager/module.py +66 -0
- polycoding-0.1.0/src/project_manager/types.py +79 -0
- polycoding-0.1.0/src/retro/README.md +432 -0
- polycoding-0.1.0/src/retro/__init__.py +23 -0
- polycoding-0.1.0/src/retro/analyzer.py +216 -0
- polycoding-0.1.0/src/retro/crews/__init__.py +5 -0
- polycoding-0.1.0/src/retro/crews/retro_crew/__init__.py +5 -0
- polycoding-0.1.0/src/retro/crews/retro_crew/config/agents.yaml +14 -0
- polycoding-0.1.0/src/retro/crews/retro_crew/config/tasks.yaml +40 -0
- polycoding-0.1.0/src/retro/crews/retro_crew/retro_crew.py +68 -0
- polycoding-0.1.0/src/retro/git_notes.py +167 -0
- polycoding-0.1.0/src/retro/persistence.py +247 -0
- polycoding-0.1.0/src/retro/types.py +67 -0
- polycoding-0.1.0/src/tasks/__init__.py +59 -0
- polycoding-0.1.0/src/tasks/config.py +102 -0
- polycoding-0.1.0/src/tasks/tasks.py +163 -0
- polycoding-0.1.0/src/tasks/worker.py +32 -0
- polycoding-0.1.0/src/tools/__init__.py +8 -0
- polycoding-0.1.0/src/tools/agents_md_loader.py +36 -0
- polycoding-0.1.0/src/tools/code_analysis/README.md +84 -0
- polycoding-0.1.0/src/tools/code_analysis/__init__.py +179 -0
- polycoding-0.1.0/src/tools/code_analysis/context_manager.py +150 -0
- polycoding-0.1.0/src/tools/code_analysis/language_support.py +154 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/__init__.py +41 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/base.py +141 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/client_pool.py +358 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/definition_tool.py +173 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/diagnostics_tool.py +222 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/hover_tool.py +136 -0
- polycoding-0.1.0/src/tools/code_analysis/lsp/references_tool.py +162 -0
- polycoding-0.1.0/src/tools/code_analysis/module.py +159 -0
- polycoding-0.1.0/src/tools/code_analysis/tree_sitter/README.md +66 -0
- polycoding-0.1.0/src/tools/code_analysis/tree_sitter/base.py +189 -0
- polycoding-0.1.0/src/tools/code_analysis/tree_sitter/types.py +131 -0
- polycoding-0.1.0/src/tools/code_analysis/types.py +131 -0
- polycoding-0.1.0/src/tools/directory_read_tool.py +86 -0
- polycoding-0.1.0/src/tools/exec_tool.py +379 -0
- polycoding-0.1.0/src/tools/file_read_tool.py +116 -0
- polycoding-0.1.0/task_templates/custom_generate_result.md +64 -0
- polycoding-0.1.0/task_templates/custom_implement.md +63 -0
- polycoding-0.1.0/tests/__init__.py +0 -0
- polycoding-0.1.0/tests/test_agents_md_loader.py +69 -0
- polycoding-0.1.0/tests/test_flows.py +119 -0
- polycoding-0.1.0/tests/test_gitcore.py +109 -0
- polycoding-0.1.0/tests/test_github_manager.py +0 -0
- polycoding-0.1.0/tests/test_project_manager_plugin.py +96 -0
- polycoding-0.1.0/tests/test_retro.py +131 -0
- polycoding-0.1.0/uv.lock +4176 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
.tox/
|
|
3
|
+
.venv/
|
|
4
|
+
*.pem
|
|
5
|
+
**/__pycache__
|
|
6
|
+
*.pyc
|
|
7
|
+
*.pyo
|
|
8
|
+
*.pyd
|
|
9
|
+
*.so
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
node_modules
|
|
28
|
+
**/node_modules
|
|
29
|
+
|
|
30
|
+
# Virtual environments
|
|
31
|
+
venv/
|
|
32
|
+
**/venv/
|
|
33
|
+
env/
|
|
34
|
+
**/env/
|
|
35
|
+
ENV/
|
|
36
|
+
**/ENV/
|
|
37
|
+
.venv/
|
|
38
|
+
**/.venv/
|
|
39
|
+
|
|
40
|
+
.ruff_cache
|
|
41
|
+
.git
|
|
42
|
+
.github
|
|
43
|
+
Dockerfile
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# IDEs
|
|
48
|
+
.vscode/
|
|
49
|
+
.idea/
|
|
50
|
+
*.swp
|
|
51
|
+
*.swo
|
|
52
|
+
*~
|
|
53
|
+
|
|
54
|
+
# Environment variables
|
|
55
|
+
.env
|
|
56
|
+
|
|
57
|
+
# OS
|
|
58
|
+
.DS_Store
|
|
59
|
+
Thumbs.db
|
|
60
|
+
|
|
61
|
+
# CrewAI specific
|
|
62
|
+
crew_output/
|
|
63
|
+
|
|
64
|
+
# Logs
|
|
65
|
+
*.log
|
|
66
|
+
|
|
67
|
+
# Testing
|
|
68
|
+
.pytest_cache/
|
|
69
|
+
.coverage
|
|
70
|
+
htmlcov/
|
|
71
|
+
|
|
72
|
+
# uv
|
|
73
|
+
.python-version
|
|
74
|
+
|
|
75
|
+
*.db
|
|
76
|
+
|
|
77
|
+
deployment
|
|
78
|
+
Makefile
|
|
79
|
+
.gitignore
|
|
80
|
+
tests
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# CrewAI Configuration
|
|
2
|
+
# Copy this file to .env and fill in your values
|
|
3
|
+
|
|
4
|
+
# OpenAI API Key (or your preferred LLM provider)
|
|
5
|
+
# CrewAI supports multiple providers: OpenAI, Anthropic, Azure, etc.
|
|
6
|
+
# See: https://docs.crewai.com/en/concepts/llms#setting-up-your-llm
|
|
7
|
+
OPENAI_API_KEY=sk-your-api-key-here
|
|
8
|
+
|
|
9
|
+
# Alternative: Anthropic API Key
|
|
10
|
+
# ANTHROPIC_API_KEY=sk-ant-your-api-key-here
|
|
11
|
+
|
|
12
|
+
# Alternative: Azure OpenAI
|
|
13
|
+
# AZURE_API_BASE=https://your-resource.openai.azure.com
|
|
14
|
+
# AZURE_API_KEY=your-azure-api-key-here
|
|
15
|
+
# AZURE_API_VERSION=2024-02-15-preview
|
|
16
|
+
# AZURE_DEPLOYMENT_NAME=gpt-4
|
|
17
|
+
|
|
18
|
+
# Serper API Key (for web search tools, if needed)
|
|
19
|
+
# SERPER_API_KEY=your-serper-api-key-here
|
|
20
|
+
|
|
21
|
+
# CrewAI Settings
|
|
22
|
+
# CREWAI_PROCESS_MODE=sequential
|
|
23
|
+
# CREWAI_VERBOSE=true
|
|
24
|
+
|
|
25
|
+
# Optional: Custom Model Configuration
|
|
26
|
+
# CREWAI_LLM=openai/gpt-4
|
|
27
|
+
# CREWAI_TEMPERATURE=0.7
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# DATABASE CONFIGURATION
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
# Database URL - supports SQLite and PostgreSQL
|
|
34
|
+
# SQLite (default): file-based, no server required
|
|
35
|
+
DATABASE_URL=sqlite:///./feature_dev.db
|
|
36
|
+
|
|
37
|
+
# PostgreSQL: production-ready, requires running PostgreSQL server
|
|
38
|
+
# Automatically uses JSONB for JSON columns
|
|
39
|
+
# DATABASE_URL=postgresql+psycopg2://user:password@localhost:5432/feature_dev
|
|
40
|
+
|
|
41
|
+
# Enable SQL query logging (useful for debugging)
|
|
42
|
+
# DATABASE_ECHO=true
|
|
43
|
+
|
|
44
|
+
# =============================================================================
|
|
45
|
+
# WEBHOOK CONFIGURATION
|
|
46
|
+
# =============================================================================
|
|
47
|
+
|
|
48
|
+
# Webhook timeout in seconds (default: 10)
|
|
49
|
+
# WEBHOOK_TIMEOUT=10
|
|
50
|
+
|
|
51
|
+
# =============================================================================
|
|
52
|
+
# DATABASE SCHEMA
|
|
53
|
+
# =============================================================================
|
|
54
|
+
#
|
|
55
|
+
# Tables:
|
|
56
|
+
#
|
|
57
|
+
# 1. flow_execution - Main flow run record
|
|
58
|
+
# - id, flow_id (unique), issue_id, task, repo, branch
|
|
59
|
+
# - current_phase, verified, tested
|
|
60
|
+
# - build_cmd, test_cmd, ci_notes, baseline, findings
|
|
61
|
+
# - current_story_id, current_story_title
|
|
62
|
+
# - pr_url, pr_number, review_status, diff
|
|
63
|
+
# - commit_title, commit_message, commit_footer
|
|
64
|
+
# - changes (JSON), tests (JSON)
|
|
65
|
+
# - created_at, updated_at
|
|
66
|
+
#
|
|
67
|
+
# 2. story - Individual user stories
|
|
68
|
+
# - id, story_id, title, description
|
|
69
|
+
# - acceptance_criteria (JSON/JSONB)
|
|
70
|
+
#
|
|
71
|
+
# 3. flow_story - Junction table (stories planned for a flow)
|
|
72
|
+
# - id, flow_id -> flow_execution.id, story_id -> story.id, order
|
|
73
|
+
#
|
|
74
|
+
# 4. completed_story - Junction table (stories completed in a flow)
|
|
75
|
+
# - id, flow_id -> flow_execution.id, story_id -> story.id
|
|
76
|
+
# - completed_at, changes, tests
|
|
77
|
+
#
|
|
78
|
+
# 5. phase_snapshot - State at each phase transition
|
|
79
|
+
# - id, flow_id -> flow_execution.id, phase
|
|
80
|
+
# - state_json (JSON/JSONB), created_at
|
|
81
|
+
#
|
|
82
|
+
# 6. webhook_config - Webhook endpoints
|
|
83
|
+
# - id, name, url, events (JSON list), active
|
|
84
|
+
#
|
|
85
|
+
# =============================================================================
|
|
86
|
+
# WEBHOOK USAGE
|
|
87
|
+
# =============================================================================
|
|
88
|
+
#
|
|
89
|
+
# Webhooks are configured in the database via webhook_config table.
|
|
90
|
+
#
|
|
91
|
+
# Example: Insert a webhook via SQL
|
|
92
|
+
# INSERT INTO webhook_config (name, url, events, active)
|
|
93
|
+
# VALUES ('slack-notify', 'https://hooks.slack.com/services/...', '["review", "create_pr"]', 1);
|
|
94
|
+
#
|
|
95
|
+
# Available phases: setup, plan_task, create_branch, implement_story,
|
|
96
|
+
# test_integration, verify, commit_changes, create_pr, review
|
|
97
|
+
# Use "*" to trigger on all phases
|
|
98
|
+
#
|
|
99
|
+
# Webhook payload format:
|
|
100
|
+
# {
|
|
101
|
+
# "phase": "review",
|
|
102
|
+
# "webhook_name": "slack-notify",
|
|
103
|
+
# "state": { ... full FeatureDevState as dict ... }
|
|
104
|
+
# }
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
venv/
|
|
25
|
+
env/
|
|
26
|
+
ENV/
|
|
27
|
+
.venv
|
|
28
|
+
|
|
29
|
+
# IDEs
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# Environment variables
|
|
37
|
+
.env
|
|
38
|
+
|
|
39
|
+
# OS
|
|
40
|
+
.DS_Store
|
|
41
|
+
Thumbs.db
|
|
42
|
+
|
|
43
|
+
# CrewAI specific
|
|
44
|
+
crew_output/
|
|
45
|
+
|
|
46
|
+
# Logs
|
|
47
|
+
*.log
|
|
48
|
+
|
|
49
|
+
# Testing
|
|
50
|
+
.pytest_cache/
|
|
51
|
+
.coverage
|
|
52
|
+
htmlcov/
|
|
53
|
+
|
|
54
|
+
# uv
|
|
55
|
+
.python-version
|
|
56
|
+
|
|
57
|
+
feature_dev.db
|
|
58
|
+
flow_state.db
|
|
59
|
+
*.db
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# Polycode — Coding Agent Guidelines
|
|
2
|
+
|
|
3
|
+
Instructions for AI coding agents (Claude Code, Cursor, etc.) working in this repository.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Project Overview
|
|
8
|
+
|
|
9
|
+
Multi-agent software development automation using CrewAI. GitHub App integration for
|
|
10
|
+
webhook-driven workflows across multiple repositories.
|
|
11
|
+
|
|
12
|
+
**Stack:** Python 3.13, CrewAI, FastAPI, Celery, Redis, PostgreSQL, Pydantic
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Build / Lint / Test Commands
|
|
17
|
+
|
|
18
|
+
### Package Management
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv sync # Install dependencies
|
|
22
|
+
uv add <package> # Add dependency
|
|
23
|
+
uv lock # Update lock file
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Linting & Type Checking
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv run ruff check . # Lint all files
|
|
30
|
+
uv run ruff check --fix . # Auto-fix lint errors
|
|
31
|
+
uv run ruff format . # Format code
|
|
32
|
+
uv run pyright # Type check (via pre-commit)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Testing
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv run pytest # Run all tests
|
|
39
|
+
uv run pytest tests/test_github_manager.py # Run single test file
|
|
40
|
+
uv run pytest tests/test_github_manager.py::test_has_label_returns_true_when_label_exists # Single test
|
|
41
|
+
uv run pytest -k "label" # Run tests matching pattern
|
|
42
|
+
uv run pytest -v # Verbose output
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Running the Application
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv run python -m project_manager.cli # CLI entry point
|
|
49
|
+
uv run uvicorn github_app.app:app # FastAPI webhook server
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Docker
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
make docker # Build and push (uses timestamp as version)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Code Style Guidelines
|
|
61
|
+
|
|
62
|
+
### Linting Rules (ruff)
|
|
63
|
+
|
|
64
|
+
- Line length: 79 characters
|
|
65
|
+
- Enabled rules: E, F, I, N, W (E501 ignored)
|
|
66
|
+
- Always run `uv run ruff check --fix .` before committing
|
|
67
|
+
|
|
68
|
+
### Imports
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
"""Module docstring."""
|
|
72
|
+
|
|
73
|
+
# 1. Standard library (alphabetical)
|
|
74
|
+
import json
|
|
75
|
+
import logging
|
|
76
|
+
import os
|
|
77
|
+
import re
|
|
78
|
+
from pathlib import Path
|
|
79
|
+
from typing import Optional, TypeVar
|
|
80
|
+
|
|
81
|
+
# 2. Third-party (alphabetical)
|
|
82
|
+
import git
|
|
83
|
+
from crewai import Flow
|
|
84
|
+
from pydantic import BaseModel, Field
|
|
85
|
+
|
|
86
|
+
# 3. Local imports (alphabetical)
|
|
87
|
+
from glm import GLMJSONLLM
|
|
88
|
+
from persistence.postgres import SessionLocal
|
|
89
|
+
from project_manager.types import ProjectConfig
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Type Annotations
|
|
93
|
+
|
|
94
|
+
Use modern Python 3.10+ syntax:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# Prefer union syntax
|
|
98
|
+
def get_issue(self, issue_id: int) -> Issue | None:
|
|
99
|
+
|
|
100
|
+
# Over Optional
|
|
101
|
+
def get_issue(self, issue_id: int) -> Optional[Issue]:
|
|
102
|
+
|
|
103
|
+
# List/dict generics without importing from typing
|
|
104
|
+
labels: list[str] = []
|
|
105
|
+
config: dict[str, Any] = {}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Pydantic Models
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
class ProjectConfig(BaseModel):
|
|
112
|
+
"""Configuration for a project manager."""
|
|
113
|
+
|
|
114
|
+
provider: str
|
|
115
|
+
repo_owner: str
|
|
116
|
+
repo_name: str
|
|
117
|
+
project_identifier: str | None = None
|
|
118
|
+
token: str | None = None
|
|
119
|
+
extra: dict[str, Any] = {}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- Always include docstrings for classes
|
|
123
|
+
- Use `Field()` for field descriptions when helpful
|
|
124
|
+
- Use `| None` for optional fields with defaults
|
|
125
|
+
|
|
126
|
+
### Naming Conventions
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
# Classes: PascalCase
|
|
130
|
+
class GitHubProjectManager:
|
|
131
|
+
|
|
132
|
+
# Functions/methods: snake_case
|
|
133
|
+
def get_open_issues(self) -> list[Issue]:
|
|
134
|
+
|
|
135
|
+
# Variables: snake_case
|
|
136
|
+
project_items = []
|
|
137
|
+
|
|
138
|
+
# Constants: UPPER_SNAKE_CASE
|
|
139
|
+
MERGE_REQUIRED_LABEL = "approved"
|
|
140
|
+
|
|
141
|
+
# Private methods: prefix with underscore
|
|
142
|
+
def _prepare_work_tree(self):
|
|
143
|
+
|
|
144
|
+
# Properties for lazy-loaded values
|
|
145
|
+
@property
|
|
146
|
+
def project_id(self) -> str:
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Error Handling
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
# Raise specific exceptions with helpful messages
|
|
153
|
+
if not token:
|
|
154
|
+
raise ValueError(
|
|
155
|
+
"GitHub token must be provided via config or GITHUB_TOKEN env var"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Handle exceptions gracefully, return sensible defaults
|
|
159
|
+
try:
|
|
160
|
+
result = self.projects_client.get_project_id(owner, number)
|
|
161
|
+
except github.UnknownObjectException:
|
|
162
|
+
log.warning(f"Project not found for {owner}")
|
|
163
|
+
return []
|
|
164
|
+
|
|
165
|
+
# Log errors with context
|
|
166
|
+
except Exception as e:
|
|
167
|
+
log.error(f"Failed to update PostgreSQL status: {e}")
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Logging
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
import logging
|
|
174
|
+
|
|
175
|
+
log = logging.getLogger(__name__)
|
|
176
|
+
|
|
177
|
+
# Use emoji prefixes for visual scanning in logs
|
|
178
|
+
log.info(f"🏹 Created worktree at: {worktree_path}")
|
|
179
|
+
log.warning(f"⚠️ No test command, skipping verification")
|
|
180
|
+
log.error(f"🚨 Failed to ensure request exists: {e}")
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Docstrings
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
def get_open_issues(self) -> list[Issue]:
|
|
187
|
+
"""Get all open issues from the repository.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
List of open issues
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def __init__(self, config: ProjectConfig) -> None:
|
|
194
|
+
"""Initialize GitHub project manager.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
config: Project configuration
|
|
198
|
+
|
|
199
|
+
Raises:
|
|
200
|
+
ValueError: If token is not provided
|
|
201
|
+
"""
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Testing Patterns
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
"""Test module docstring."""
|
|
208
|
+
|
|
209
|
+
from unittest.mock import MagicMock
|
|
210
|
+
|
|
211
|
+
from project_manager.github import GitHubProjectManager
|
|
212
|
+
from project_manager.types import ProjectConfig
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_has_label_returns_true_when_label_exists():
|
|
216
|
+
"""Test that has_label returns True when the label is present."""
|
|
217
|
+
# Arrange
|
|
218
|
+
config = ProjectConfig(
|
|
219
|
+
repo_owner="testowner",
|
|
220
|
+
repo_name="testrepo",
|
|
221
|
+
token="fake_token",
|
|
222
|
+
)
|
|
223
|
+
manager = GitHubProjectManager(config)
|
|
224
|
+
mock_repo = MagicMock()
|
|
225
|
+
mock_pr = MagicMock()
|
|
226
|
+
mock_pr.labels = [MagicMock(name="approved")]
|
|
227
|
+
mock_repo.get_pull.return_value = mock_pr
|
|
228
|
+
manager.github_client.get_repo = MagicMock(return_value=mock_repo)
|
|
229
|
+
|
|
230
|
+
# Act
|
|
231
|
+
result = manager.has_label(123, "approved")
|
|
232
|
+
|
|
233
|
+
# Assert
|
|
234
|
+
assert result is True
|
|
235
|
+
mock_repo.get_pull.assert_called_once_with(123)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
- Use descriptive test names: `test_<method>_<scenario>_<expected_result>`
|
|
239
|
+
- AAA pattern: Arrange, Act, Assert
|
|
240
|
+
- Use `unittest.mock` for mocking
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Project Structure
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
polycode/
|
|
248
|
+
├── src/
|
|
249
|
+
│ ├── project_manager/ # GitHub project management
|
|
250
|
+
│ ├── github_app/ # GitHub App webhook server
|
|
251
|
+
│ ├── celery_tasks/ # Async task processing
|
|
252
|
+
│ ├── persistence/ # Database layer
|
|
253
|
+
│ ├── feature_dev/ # Feature development crew
|
|
254
|
+
│ └── flowbase.py # Base flow classes
|
|
255
|
+
├── tests/ # Test files
|
|
256
|
+
├── pyproject.toml # Project config
|
|
257
|
+
└── .env # Environment variables
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Pre-commit Hooks
|
|
263
|
+
|
|
264
|
+
Configured in `.pre-commit-config.yaml`:
|
|
265
|
+
|
|
266
|
+
- trailing-whitespace
|
|
267
|
+
- commitizen (conventional commits with gitmoji)
|
|
268
|
+
- markdownlint
|
|
269
|
+
- pyright (type checking)
|
|
270
|
+
|
|
271
|
+
Run manually: `pre-commit run --all-files`
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Environment Variables
|
|
276
|
+
|
|
277
|
+
Required in `.env`:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
GITHUB_TOKEN=ghp_...
|
|
281
|
+
DATABASE_URL=postgresql://...
|
|
282
|
+
REDIS_HOST=localhost
|
|
283
|
+
REDIS_PORT=6379
|
|
284
|
+
OPENAI_API_KEY=sk-...
|
|
285
|
+
OPENAI_URL_BASE=http://...
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## CrewAI Reference
|
|
291
|
+
|
|
292
|
+
See `src/AGENTS.md` for detailed CrewAI patterns, agent/task configuration, and flows.
|
|
293
|
+
|
|
294
|
+
**Key points:**
|
|
295
|
+
|
|
296
|
+
- Use `crewai.LLM` or string shorthand like `"openai/gpt-4o"`
|
|
297
|
+
- Agents and tasks in YAML configs
|
|
298
|
+
- `@CrewBase` decorator on crew classes
|
|
299
|
+
- `# type: ignore[index]` for config dictionary access
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Use the official Python 3.13 slim image as the base
|
|
2
|
+
FROM python:3.13-slim AS base
|
|
3
|
+
|
|
4
|
+
# Set environment variables to avoid interactive prompts during installation
|
|
5
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
6
|
+
|
|
7
|
+
# Install system dependencies, Node.js (from NodeSource), and clean up
|
|
8
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
9
|
+
git \
|
|
10
|
+
ssh \
|
|
11
|
+
curl \
|
|
12
|
+
ca-certificates \
|
|
13
|
+
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
|
14
|
+
&& apt-get install -y nodejs \
|
|
15
|
+
&& apt-get clean \
|
|
16
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
17
|
+
RUN node --version && npm --version && npm install -g pnpm && pnpm --version
|
|
18
|
+
|
|
19
|
+
FROM base
|
|
20
|
+
WORKDIR /app
|
|
21
|
+
|
|
22
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
23
|
+
RUN pip install --no-cache-dir "crewai[litellm]>=1.10.0b1" && uv sync
|
|
24
|
+
|
|
25
|
+
COPY entrypooint.sh /usr/local/bin/entrypoint.sh
|
|
26
|
+
RUN chmod +x /usr/local/bin/entrypoint.sh
|
|
27
|
+
|
|
28
|
+
# Creates a non-root user and adds permission to access the /app folder
|
|
29
|
+
RUN useradd --create-home appuser \
|
|
30
|
+
&& chown -R appuser /app
|
|
31
|
+
USER appuser
|
|
32
|
+
|
|
33
|
+
# Need to whitelist fingerprint of github
|
|
34
|
+
RUN mkdir /home/appuser/.ssh && ssh-keyscan github.com >> /home/appuser/.ssh/known_hosts
|
|
35
|
+
|
|
36
|
+
VOLUME [ "/data" ]
|
|
37
|
+
COPY . .
|
|
38
|
+
|
|
39
|
+
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
polycoding-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2026, ChainSquad GmbH
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the “Software”), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to
|
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
8
|
+
so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
20
|
+
|