generated from coulomb/repo-seed
feat: transform to agent coordination platform with comprehensive documentation
Transform Issue Facade from a universal CLI tool into an agent coordination platform with comprehensive documentation and enhanced capabilities for autonomous coding agents. Major Changes: - Complete README rewrite focusing on agent-driven coordination - New comprehensive documentation (AGENT_INTEGRATION.md, CLAUDE.md, ROADMAP.md) - Capability integration setup with CAPABILITY.yaml and integration scripts - Enhanced Makefile with local development targets for easier workflows Bug Fixes: - Fix schema initialization using executescript() for multi-line SQL support - Disable FTS5 triggers due to compatibility issues (documented for future re-enablement) Features: - Enhanced CLI list command with full parameter passthrough - New examples directory with agent integration patterns - New comprehensive test suite (test_core_models.py, test_local_backend.py) Code Quality: - Remove @cached_property decorators for Label properties (simplification) - Clean up test organization (removed old test_gitea_integration.py) This milestone establishes Issue Facade as a production-ready coordination layer for multi-agent software development, with clear integration paths and comprehensive developer documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
675
AGENT_INTEGRATION.md
Normal file
675
AGENT_INTEGRATION.md
Normal file
@@ -0,0 +1,675 @@
|
||||
# Agent Integration Guide
|
||||
|
||||
**Issue Facade for Autonomous Coding Agent Coordination**
|
||||
|
||||
## Purpose
|
||||
|
||||
The **Issue Facade** capability provides a standardized interface for autonomous coding agents to coordinate project implementation through issue tracking. Instead of agents directly interfacing with platform-specific APIs (GitHub, GitLab, Gitea), they use a unified abstraction that works consistently across backends.
|
||||
|
||||
### Why Issue Tracking for Agent Coordination?
|
||||
|
||||
Issue tracking provides a natural coordination mechanism for multi-agent software development:
|
||||
|
||||
- **Task Distribution**: Issues represent discrete units of work that agents can claim and execute
|
||||
- **State Management**: Issue states (open, in_progress, closed) track progress across the team
|
||||
- **Communication Channel**: Comments enable inter-agent communication and human oversight
|
||||
- **Progress Visibility**: Labels, assignees, and milestones provide real-time project status
|
||||
- **Audit Trail**: Complete history of who did what and when
|
||||
- **Human Integration**: Human developers can seamlessly participate in agent-driven projects
|
||||
|
||||
## Current Status: Production-Ready with Manual Setup
|
||||
|
||||
### What Works Now (v1.0)
|
||||
|
||||
✅ **Complete CRUD Operations**
|
||||
- Create, read, update, delete issues
|
||||
- Full label management
|
||||
- User and assignee handling
|
||||
- Milestone operations
|
||||
- Comment threads
|
||||
|
||||
✅ **Gitea Backend** (Production-Ready)
|
||||
- Complete API integration
|
||||
- Rate limiting and error handling
|
||||
- State mapping (open/in_progress/blocked → open/closed)
|
||||
- Sync support with local backup
|
||||
|
||||
✅ **Local SQLite Backend** (Fully Functional)
|
||||
- Offline operation
|
||||
- Complete data model
|
||||
- Sync with remote backends
|
||||
- Fast queries and filtering
|
||||
|
||||
✅ **Agent-Friendly Features**
|
||||
- JSON output mode for machine parsing
|
||||
- Programmatic Python API
|
||||
- Comprehensive filtering
|
||||
- Batch operations
|
||||
- Type-safe models
|
||||
|
||||
### Current Limitations
|
||||
|
||||
⚠️ **Manual Configuration Required**
|
||||
- No auto-detection from git remotes (yet)
|
||||
- Backend configuration is manual one-time setup
|
||||
- No environment-variable-only mode (yet)
|
||||
|
||||
⚠️ **Hardcoded User Context**
|
||||
- CLI operations use "cli-user" placeholder
|
||||
- Agent identity needs to be managed externally
|
||||
|
||||
⚠️ **Basic Conflict Resolution**
|
||||
- Sync detects conflicts but doesn't auto-resolve
|
||||
- Manual intervention required for complex merges
|
||||
|
||||
## Quick Start for Agents
|
||||
|
||||
### 1. Installation
|
||||
|
||||
```bash
|
||||
cd capabilities/issue-facade
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
### 2. Backend Configuration (One-Time Setup)
|
||||
|
||||
**For Gitea Projects:**
|
||||
|
||||
```bash
|
||||
# Configure Gitea backend
|
||||
export GITEA_API_TOKEN="your-token-here"
|
||||
|
||||
issue backend add my-project gitea
|
||||
# Prompts for:
|
||||
# - Gitea URL: https://gitea.example.com
|
||||
# - Owner: your-org
|
||||
# - Repo: your-project
|
||||
# - Token: (reads from GITEA_API_TOKEN)
|
||||
|
||||
# Verify connection
|
||||
issue backend test my-project
|
||||
|
||||
# Set as default
|
||||
issue backend set-default my-project
|
||||
```
|
||||
|
||||
**For Local/Offline Work:**
|
||||
|
||||
```bash
|
||||
# Configure local SQLite backend
|
||||
issue backend add local-work local
|
||||
# Prompts for:
|
||||
# - Database path: .issue-facade/issues.db
|
||||
|
||||
issue backend set-default local-work
|
||||
```
|
||||
|
||||
### 3. Basic Agent Operations
|
||||
|
||||
```bash
|
||||
# List open issues assigned to an agent
|
||||
issue list --state=open --assignee=agent-coder --format=json
|
||||
|
||||
# Create a new issue
|
||||
issue create "Implement user authentication" \
|
||||
--label=feature --label=priority:high \
|
||||
--assignee=agent-coder
|
||||
|
||||
# Update issue state
|
||||
issue edit 42 --state=in_progress
|
||||
|
||||
# Add progress comment
|
||||
issue comment 42 "Completed database schema migration"
|
||||
|
||||
# Close when done
|
||||
issue close 42 --comment="Implementation complete, tests passing"
|
||||
```
|
||||
|
||||
## Agent Workflow Patterns
|
||||
|
||||
### Pattern 1: Single Agent, Task Execution
|
||||
|
||||
**Scenario**: One agent implements features from an issue backlog.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Agent workflow script
|
||||
|
||||
# 1. Get next available task
|
||||
ISSUE=$(issue list --state=open --label=ready \
|
||||
--format=json --limit=1 | jq -r '.[0].number')
|
||||
|
||||
# 2. Claim the issue
|
||||
issue edit $ISSUE --assignee=agent-coder --state=in_progress
|
||||
issue comment $ISSUE "Starting implementation"
|
||||
|
||||
# 3. Execute work
|
||||
# ... agent implements the feature ...
|
||||
|
||||
# 4. Report completion
|
||||
issue comment $ISSUE "Implementation complete. Files changed: src/auth.py, tests/test_auth.py"
|
||||
issue close $ISSUE --comment="Ready for review"
|
||||
```
|
||||
|
||||
### Pattern 2: Multi-Agent Coordination
|
||||
|
||||
**Scenario**: Multiple specialized agents work on different aspects.
|
||||
|
||||
```bash
|
||||
# Agent 1 (Coder) - Claims and implements
|
||||
issue list --label=needs-implementation --state=open --format=json | \
|
||||
jq -r '.[0].number' | \
|
||||
xargs -I {} issue edit {} --assignee=agent-coder --state=in_progress
|
||||
|
||||
# Agent 2 (Reviewer) - Reviews completed work
|
||||
issue list --label=needs-review --state=closed --format=json | \
|
||||
jq -r '.[0].number' | \
|
||||
xargs -I {} sh -c 'issue comment {} "Code review complete. Approved."'
|
||||
|
||||
# Agent 3 (Tester) - Runs tests on reviewed code
|
||||
issue list --label=reviewed --state=closed --format=json | \
|
||||
jq -r '.[0].number' | \
|
||||
xargs -I {} sh -c 'issue comment {} "All tests passing. Deploying to staging."'
|
||||
```
|
||||
|
||||
### Pattern 3: Agent-Human Collaboration
|
||||
|
||||
**Scenario**: Agents implement, humans review and approve.
|
||||
|
||||
```python
|
||||
# Agent creates implementation issues from requirements
|
||||
from issue_tracker.backends.gitea import GiteaBackend
|
||||
from issue_tracker.core.models import Issue, Label, IssueState
|
||||
from datetime import datetime, timezone
|
||||
|
||||
backend = GiteaBackend()
|
||||
backend.connect({
|
||||
'base_url': 'https://gitea.example.com',
|
||||
'token': os.environ['GITEA_API_TOKEN'],
|
||||
'owner': 'myorg',
|
||||
'repo': 'myproject'
|
||||
})
|
||||
|
||||
# Agent breaks down feature into tasks
|
||||
feature_issue = backend.get_issue_by_number(100)
|
||||
subtasks = [
|
||||
"Implement database schema",
|
||||
"Create API endpoints",
|
||||
"Add frontend components",
|
||||
"Write integration tests"
|
||||
]
|
||||
|
||||
for task in subtasks:
|
||||
issue = Issue(
|
||||
id=None, number=0,
|
||||
title=f"{feature_issue.title}: {task}",
|
||||
description=f"Subtask of #{feature_issue.number}\n\n{task}",
|
||||
state=IssueState.OPEN,
|
||||
created_at=datetime.now(timezone.utc),
|
||||
updated_at=datetime.now(timezone.utc),
|
||||
labels=[
|
||||
Label(name="agent-generated"),
|
||||
Label(name="needs-implementation"),
|
||||
Label(name="parent:100")
|
||||
]
|
||||
)
|
||||
backend.create_issue(issue)
|
||||
|
||||
# Human reviews and approves/rejects via comments
|
||||
# Agent monitors for approval comments and proceeds
|
||||
```
|
||||
|
||||
## Programmatic API for Agents
|
||||
|
||||
### Python Integration
|
||||
|
||||
```python
|
||||
from issue_tracker.backends.gitea import GiteaBackend
|
||||
from issue_tracker.core.models import Issue, Label, IssueState, User
|
||||
from issue_tracker.core.interfaces import IssueFilter
|
||||
from datetime import datetime, timezone
|
||||
import os
|
||||
|
||||
# Initialize backend
|
||||
backend = GiteaBackend()
|
||||
backend.connect({
|
||||
'base_url': os.environ['GITEA_URL'],
|
||||
'token': os.environ['GITEA_API_TOKEN'],
|
||||
'owner': os.environ['GITEA_OWNER'],
|
||||
'repo': os.environ['GITEA_REPO']
|
||||
})
|
||||
|
||||
# Query issues
|
||||
filter_criteria = IssueFilter(
|
||||
state='open',
|
||||
labels=['bug', 'priority:high'],
|
||||
assignee='agent-coder',
|
||||
limit=10
|
||||
)
|
||||
issues = backend.list_issues(filter_criteria)
|
||||
|
||||
# Create issue
|
||||
new_issue = Issue(
|
||||
id=None,
|
||||
number=0,
|
||||
title="Fix memory leak in parser",
|
||||
description="Detected memory leak in parse_document() function",
|
||||
state=IssueState.OPEN,
|
||||
created_at=datetime.now(timezone.utc),
|
||||
updated_at=datetime.now(timezone.utc),
|
||||
labels=[
|
||||
Label(name="bug"),
|
||||
Label(name="priority:critical"),
|
||||
Label(name="agent-detected")
|
||||
],
|
||||
assignees=[User(id="agent-coder", username="agent-coder")]
|
||||
)
|
||||
created = backend.create_issue(new_issue)
|
||||
|
||||
# Update issue
|
||||
created.state = IssueState.IN_PROGRESS
|
||||
backend.update_issue(created)
|
||||
|
||||
# Add comment
|
||||
from issue_tracker.core.models import Comment
|
||||
comment = Comment(
|
||||
id=None,
|
||||
body="Analysis complete. Root cause: unclosed file handles in line 234",
|
||||
author=User(id="agent-coder", username="agent-coder"),
|
||||
created_at=datetime.now(timezone.utc)
|
||||
)
|
||||
backend.add_comment(created.id, comment)
|
||||
|
||||
# Close issue
|
||||
created.state = IssueState.CLOSED
|
||||
created.closed_at = datetime.now(timezone.utc)
|
||||
backend.update_issue(created)
|
||||
```
|
||||
|
||||
### Advanced Filtering
|
||||
|
||||
```python
|
||||
# Get all high-priority bugs not assigned
|
||||
critical_bugs = backend.list_issues(IssueFilter(
|
||||
state='open',
|
||||
labels=['bug', 'priority:critical']
|
||||
))
|
||||
unassigned = [i for i in critical_bugs if not i.assignees]
|
||||
|
||||
# Get stale issues (not updated in 7 days)
|
||||
from datetime import timedelta
|
||||
stale_threshold = datetime.now(timezone.utc) - timedelta(days=7)
|
||||
stale_issues = backend.list_issues(IssueFilter(
|
||||
state='open',
|
||||
updated_before=stale_threshold
|
||||
))
|
||||
|
||||
# Search by text
|
||||
search_results = backend.search_issues("authentication", limit=20)
|
||||
```
|
||||
|
||||
## Agent Coordination Strategies
|
||||
|
||||
### Strategy 1: Label-Based Role Assignment
|
||||
|
||||
Use labels to indicate agent specialization:
|
||||
|
||||
```python
|
||||
# Agent types
|
||||
AGENT_ROLES = {
|
||||
'agent:coder': ['feature', 'bug', 'refactor'],
|
||||
'agent:tester': ['needs-testing', 'test-failure'],
|
||||
'agent:reviewer': ['needs-review', 'code-quality'],
|
||||
'agent:documenter': ['documentation', 'api-docs']
|
||||
}
|
||||
|
||||
# Each agent filters by their role
|
||||
def get_agent_tasks(agent_type):
|
||||
role_labels = AGENT_ROLES[agent_type]
|
||||
all_tasks = []
|
||||
for label in role_labels:
|
||||
tasks = backend.list_issues(IssueFilter(
|
||||
state='open',
|
||||
labels=[label, agent_type]
|
||||
))
|
||||
all_tasks.extend(tasks)
|
||||
return all_tasks
|
||||
```
|
||||
|
||||
### Strategy 2: State Machine Workflow
|
||||
|
||||
Use issue states to track progress through pipeline:
|
||||
|
||||
```
|
||||
open → in_progress → needs_review → closed
|
||||
↓ ↓ ↓
|
||||
blocked blocked blocked
|
||||
```
|
||||
|
||||
```python
|
||||
def advance_issue_state(issue_number):
|
||||
issue = backend.get_issue_by_number(issue_number)
|
||||
|
||||
state_transitions = {
|
||||
IssueState.OPEN: IssueState.IN_PROGRESS,
|
||||
IssueState.IN_PROGRESS: IssueState.CLOSED # or needs_review
|
||||
}
|
||||
|
||||
if issue.state in state_transitions:
|
||||
issue.state = state_transitions[issue.state]
|
||||
backend.update_issue(issue)
|
||||
return True
|
||||
return False
|
||||
```
|
||||
|
||||
### Strategy 3: Comment-Based Communication
|
||||
|
||||
Use structured comments for agent-to-agent messages:
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
def post_agent_message(issue_id, message_type, data):
|
||||
"""Post structured message for other agents"""
|
||||
message = {
|
||||
'type': message_type,
|
||||
'agent': 'agent-coder',
|
||||
'timestamp': datetime.now(timezone.utc).isoformat(),
|
||||
'data': data
|
||||
}
|
||||
comment = Comment(
|
||||
id=None,
|
||||
body=f"```agent-message\n{json.dumps(message, indent=2)}\n```",
|
||||
author=User(id="agent-coder", username="agent-coder"),
|
||||
created_at=datetime.now(timezone.utc)
|
||||
)
|
||||
backend.add_comment(issue_id, comment)
|
||||
|
||||
def read_agent_messages(issue_id, message_type=None):
|
||||
"""Read structured messages from other agents"""
|
||||
comments = backend.get_comments(issue_id)
|
||||
messages = []
|
||||
for comment in comments:
|
||||
if '```agent-message' in comment.body:
|
||||
try:
|
||||
json_str = comment.body.split('```agent-message\n')[1].split('\n```')[0]
|
||||
msg = json.loads(json_str)
|
||||
if message_type is None or msg['type'] == message_type:
|
||||
messages.append(msg)
|
||||
except (IndexError, json.JSONDecodeError):
|
||||
continue
|
||||
return messages
|
||||
|
||||
# Usage:
|
||||
post_agent_message(42, 'implementation_complete', {
|
||||
'files_changed': ['src/auth.py', 'tests/test_auth.py'],
|
||||
'tests_passing': True,
|
||||
'coverage': 95.2
|
||||
})
|
||||
|
||||
# Later, reviewer agent reads:
|
||||
results = read_agent_messages(42, 'implementation_complete')
|
||||
```
|
||||
|
||||
## Synchronization and Backup
|
||||
|
||||
### Sync Local and Remote
|
||||
|
||||
```bash
|
||||
# Pull all issues to local backup
|
||||
issue backend add backup local
|
||||
issue sync pull gitea-remote backup
|
||||
|
||||
# Work offline with local backend
|
||||
issue backend set-default backup
|
||||
issue create "Offline work item" --label=offline
|
||||
|
||||
# Sync back when online
|
||||
issue sync push backup gitea-remote
|
||||
```
|
||||
|
||||
### Conflict Handling
|
||||
|
||||
```python
|
||||
# Check for conflicts before sync
|
||||
from issue_tracker.cli.sync_commands import sync_pull
|
||||
|
||||
try:
|
||||
sync_pull(source='remote', target='local', dry_run=True)
|
||||
except ConflictError as e:
|
||||
# Conflicts detected
|
||||
for conflict in e.conflicts:
|
||||
print(f"Conflict on issue {conflict['issue_number']}")
|
||||
print(f" Local updated: {conflict['local_updated']}")
|
||||
print(f" Remote updated: {conflict['remote_updated']}")
|
||||
|
||||
# Resolve by choosing newer timestamp
|
||||
sync_pull(source='remote', target='local', force=True)
|
||||
```
|
||||
|
||||
## Current Workarounds for Limitations
|
||||
|
||||
### Workaround 1: Agent Identity
|
||||
|
||||
Since "cli-user" is hardcoded, use labels or comments to indicate agent:
|
||||
|
||||
```python
|
||||
# Add agent identifier to all operations
|
||||
agent_id = "agent-coder-v1"
|
||||
|
||||
# In issue creation
|
||||
labels.append(Label(name=f"created-by:{agent_id}"))
|
||||
|
||||
# In comments
|
||||
comment.body = f"[{agent_id}] {actual_message}"
|
||||
```
|
||||
|
||||
### Workaround 2: Issue Claiming
|
||||
|
||||
No built-in locking, so use assignee + comment:
|
||||
|
||||
```python
|
||||
def claim_issue(issue_number, agent_id, timeout_minutes=30):
|
||||
issue = backend.get_issue_by_number(issue_number)
|
||||
|
||||
# Check if already claimed
|
||||
if issue.assignees:
|
||||
# Check claim age from comments
|
||||
comments = backend.get_comments(issue.id)
|
||||
claim_comments = [c for c in comments if 'CLAIMED' in c.body]
|
||||
if claim_comments:
|
||||
last_claim = claim_comments[-1].created_at
|
||||
age = datetime.now(timezone.utc) - last_claim
|
||||
if age.total_seconds() < timeout_minutes * 60:
|
||||
return False # Still claimed
|
||||
|
||||
# Claim it
|
||||
issue.assignees = [User(id=agent_id, username=agent_id)]
|
||||
issue.state = IssueState.IN_PROGRESS
|
||||
backend.update_issue(issue)
|
||||
|
||||
backend.add_comment(issue.id, Comment(
|
||||
id=None,
|
||||
body=f"CLAIMED by {agent_id} at {datetime.now(timezone.utc).isoformat()}",
|
||||
author=User(id=agent_id, username=agent_id),
|
||||
created_at=datetime.now(timezone.utc)
|
||||
))
|
||||
return True
|
||||
```
|
||||
|
||||
### Workaround 3: Manual Repository Configuration
|
||||
|
||||
Create a setup script for each project:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# setup-issue-tracking.sh
|
||||
|
||||
cat > .issue-facade-config << EOF
|
||||
GITEA_URL=https://gitea.example.com
|
||||
GITEA_OWNER=myorg
|
||||
GITEA_REPO=myproject
|
||||
GITEA_TOKEN_FILE=~/.secrets/gitea-token
|
||||
EOF
|
||||
|
||||
# Load config and configure backend
|
||||
source .issue-facade-config
|
||||
export GITEA_API_TOKEN=$(cat $GITEA_TOKEN_FILE)
|
||||
|
||||
issue backend add $(basename $(pwd)) gitea <<INPUT
|
||||
$GITEA_URL
|
||||
$GITEA_OWNER
|
||||
$GITEA_REPO
|
||||
INPUT
|
||||
|
||||
issue backend set-default $(basename $(pwd))
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Efficient Querying
|
||||
|
||||
```python
|
||||
# BAD: Get all issues then filter in Python
|
||||
all_issues = backend.list_issues()
|
||||
my_issues = [i for i in all_issues if i.assignees and i.assignees[0].username == 'agent-coder']
|
||||
|
||||
# GOOD: Use backend filtering
|
||||
my_issues = backend.list_issues(IssueFilter(
|
||||
assignee='agent-coder',
|
||||
state='open'
|
||||
))
|
||||
```
|
||||
|
||||
### Batch Operations
|
||||
|
||||
```python
|
||||
# BAD: Update issues one by one
|
||||
for issue_number in [1, 2, 3, 4, 5]:
|
||||
issue = backend.get_issue_by_number(issue_number)
|
||||
issue.labels.append(Label(name="batch-processed"))
|
||||
backend.update_issue(issue)
|
||||
|
||||
# GOOD: Use local backend for bulk operations
|
||||
from issue_tracker.backends.local import LocalSQLiteBackend
|
||||
|
||||
local = LocalSQLiteBackend()
|
||||
local.connect({'db_path': '/tmp/batch.db'})
|
||||
|
||||
# Pull from remote
|
||||
for issue_number in [1, 2, 3, 4, 5]:
|
||||
issue = backend.get_issue_by_number(issue_number)
|
||||
local.create_issue(issue)
|
||||
|
||||
# Bulk update locally
|
||||
issues = local.list_issues()
|
||||
for issue in issues:
|
||||
issue.labels.append(Label(name="batch-processed"))
|
||||
local.update_issue(issue)
|
||||
|
||||
# Push back to remote
|
||||
for issue in local.list_issues():
|
||||
backend.update_issue(issue)
|
||||
```
|
||||
|
||||
### Caching
|
||||
|
||||
```python
|
||||
# Cache issue list for short-lived operations
|
||||
import functools
|
||||
import time
|
||||
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def get_open_issues_cached():
|
||||
return backend.list_issues(IssueFilter(state='open'))
|
||||
|
||||
# Invalidate cache after 60 seconds
|
||||
last_fetch = time.time()
|
||||
if time.time() - last_fetch > 60:
|
||||
get_open_issues_cached.cache_clear()
|
||||
last_fetch = time.time()
|
||||
```
|
||||
|
||||
## Roadmap: Future Enhancements
|
||||
|
||||
### Phase 1: Auto-Configuration (v1.1)
|
||||
- Automatic git remote detection
|
||||
- Environment-variable-only setup
|
||||
- Per-repository `.issue-facade/config.json` support
|
||||
- `issue config detect` command
|
||||
|
||||
### Phase 2: Agent Features (v1.2)
|
||||
- Agent identity management
|
||||
- Issue claiming/locking API
|
||||
- Structured metadata fields for agent state
|
||||
- Webhook support for reactive agents
|
||||
|
||||
### Phase 3: Advanced Coordination (v2.0)
|
||||
- Issue dependency tracking
|
||||
- Query DSL: `is:open assignee:me label:bug,critical`
|
||||
- Activity streams and event logs
|
||||
- Multi-agent conflict resolution strategies
|
||||
- Distributed locking for concurrent operations
|
||||
|
||||
## Examples Repository
|
||||
|
||||
See `examples/agents/` for complete working examples:
|
||||
|
||||
- `simple_task_executor.py` - Single agent claiming and executing tasks
|
||||
- `multi_agent_pipeline.py` - Multiple agents in CI/CD-like workflow
|
||||
- `human_in_loop.py` - Agents with human approval gates
|
||||
- `monitoring_agent.py` - Agent that monitors issue health and sends alerts
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Backend not configured"
|
||||
|
||||
```bash
|
||||
# List configured backends
|
||||
issue backend list
|
||||
|
||||
# If empty, configure one
|
||||
issue backend add myproject gitea
|
||||
```
|
||||
|
||||
### "Authentication failed"
|
||||
|
||||
```bash
|
||||
# Check token is valid
|
||||
issue backend test myproject
|
||||
|
||||
# Reconfigure with correct token
|
||||
export GITEA_API_TOKEN="new-token"
|
||||
issue backend remove myproject
|
||||
issue backend add myproject gitea
|
||||
```
|
||||
|
||||
### "Issue not found"
|
||||
|
||||
```python
|
||||
# Gitea uses backend_id, not number
|
||||
issue = backend.get_issue_by_number(42) # Correct
|
||||
# issue = backend.get_issue("42") # Wrong - needs backend_id
|
||||
```
|
||||
|
||||
### "Sync conflicts"
|
||||
|
||||
```bash
|
||||
# Force sync (overwrites target)
|
||||
issue sync pull source target --force
|
||||
|
||||
# Or manually resolve
|
||||
issue list --backend=source --format=json > source.json
|
||||
issue list --backend=target --format=json > target.json
|
||||
# Compare and decide which to keep
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation**: See `CLAUDE.md` for development guide
|
||||
- **Tests**: Run `make test` to verify installation
|
||||
- **Issues**: Report issues in the main markitect repository
|
||||
|
||||
## License
|
||||
|
||||
MIT License - See LICENSE file
|
||||
Reference in New Issue
Block a user