initial setup: planning documents updated
This commit is contained in:
831
docs/references/MCP-GITEA.md
Normal file
831
docs/references/MCP-GITEA.md
Normal file
@@ -0,0 +1,831 @@
|
|||||||
|
# Gitea MCP Server Reference
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Gitea MCP Server provides integration with Gitea for issue management, label operations, and repository tracking. It's shared by both `projman` and `projman-pmo` plugins, detecting its operating mode based on environment variables.
|
||||||
|
|
||||||
|
**Location:** `mcp-servers/gitea/` (repository root)
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Issue CRUD operations
|
||||||
|
- Label taxonomy management (43-label system)
|
||||||
|
- Mode detection (project-scoped vs company-wide)
|
||||||
|
- Hybrid configuration (system + project level)
|
||||||
|
- Python 3.11+ implementation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Mode Detection
|
||||||
|
|
||||||
|
The MCP server operates in two modes based on environment variables:
|
||||||
|
|
||||||
|
**Project Mode (projman):**
|
||||||
|
- When `GITEA_REPO` is present
|
||||||
|
- Operates on single repository
|
||||||
|
- Used by projman plugin
|
||||||
|
|
||||||
|
**Company Mode (pmo):**
|
||||||
|
- When `GITEA_REPO` is absent
|
||||||
|
- Operates on all repositories in organization
|
||||||
|
- Used by projman-pmo plugin
|
||||||
|
|
||||||
|
```python
|
||||||
|
# mcp-servers/gitea/mcp_server/config.py
|
||||||
|
def load(self):
|
||||||
|
# ... load configs ...
|
||||||
|
|
||||||
|
self.repo = os.getenv('GITEA_REPO') # Optional
|
||||||
|
|
||||||
|
if self.repo:
|
||||||
|
self.mode = 'project'
|
||||||
|
logger.info(f"Running in project mode: {self.repo}")
|
||||||
|
else:
|
||||||
|
self.mode = 'company'
|
||||||
|
logger.info("Running in company-wide mode (PMO)")
|
||||||
|
|
||||||
|
return {
|
||||||
|
'api_url': self.api_url,
|
||||||
|
'api_token': self.api_token,
|
||||||
|
'owner': self.owner,
|
||||||
|
'repo': self.repo,
|
||||||
|
'mode': self.mode
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### System-Level Configuration
|
||||||
|
|
||||||
|
**File:** `~/.config/claude/gitea.env`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
||||||
|
GITEA_API_TOKEN=your_gitea_token
|
||||||
|
GITEA_OWNER=hyperhivelabs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Setup:**
|
||||||
|
```bash
|
||||||
|
# Create config directory
|
||||||
|
mkdir -p ~/.config/claude
|
||||||
|
|
||||||
|
# Create gitea.env
|
||||||
|
cat > ~/.config/claude/gitea.env << EOF
|
||||||
|
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
||||||
|
GITEA_API_TOKEN=your_token
|
||||||
|
GITEA_OWNER=hyperhivelabs
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Secure the file
|
||||||
|
chmod 600 ~/.config/claude/gitea.env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project-Level Configuration
|
||||||
|
|
||||||
|
**File:** `project-root/.env`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Repository name (project mode only)
|
||||||
|
GITEA_REPO=cuisineflow
|
||||||
|
```
|
||||||
|
|
||||||
|
**Setup:**
|
||||||
|
```bash
|
||||||
|
# In each project root
|
||||||
|
echo "GITEA_REPO=cuisineflow" > .env
|
||||||
|
|
||||||
|
# Add to .gitignore
|
||||||
|
echo ".env" >> .gitignore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Loading Strategy
|
||||||
|
|
||||||
|
```python
|
||||||
|
# mcp-servers/gitea/mcp_server/config.py
|
||||||
|
from pathlib import Path
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
from typing import Dict, Optional
|
||||||
|
|
||||||
|
class GiteaConfig:
|
||||||
|
"""Hybrid configuration loader"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.api_url: Optional[str] = None
|
||||||
|
self.api_token: Optional[str] = None
|
||||||
|
self.owner: Optional[str] = None
|
||||||
|
self.repo: Optional[str] = None
|
||||||
|
self.mode: str = 'project'
|
||||||
|
|
||||||
|
def load(self) -> Dict[str, str]:
|
||||||
|
"""
|
||||||
|
Load configuration from system and project levels.
|
||||||
|
Project-level configuration overrides system-level.
|
||||||
|
"""
|
||||||
|
# Load system config
|
||||||
|
system_config = Path.home() / '.config' / 'claude' / 'gitea.env'
|
||||||
|
if system_config.exists():
|
||||||
|
load_dotenv(system_config)
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError(
|
||||||
|
f"System config not found: {system_config}\n"
|
||||||
|
"Create it with: mkdir -p ~/.config/claude && "
|
||||||
|
"cat > ~/.config/claude/gitea.env"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Load project config (overrides system)
|
||||||
|
project_config = Path.cwd() / '.env'
|
||||||
|
if project_config.exists():
|
||||||
|
load_dotenv(project_config, override=True)
|
||||||
|
|
||||||
|
# Extract values
|
||||||
|
self.api_url = os.getenv('GITEA_API_URL')
|
||||||
|
self.api_token = os.getenv('GITEA_API_TOKEN')
|
||||||
|
self.owner = os.getenv('GITEA_OWNER')
|
||||||
|
self.repo = os.getenv('GITEA_REPO') # Optional for PMO
|
||||||
|
|
||||||
|
# Detect mode
|
||||||
|
self.mode = 'project' if self.repo else 'company'
|
||||||
|
|
||||||
|
# Validate required variables
|
||||||
|
self._validate()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'api_url': self.api_url,
|
||||||
|
'api_token': self.api_token,
|
||||||
|
'owner': self.owner,
|
||||||
|
'repo': self.repo,
|
||||||
|
'mode': self.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
def _validate(self) -> None:
|
||||||
|
"""Validate that required configuration is present"""
|
||||||
|
required = {
|
||||||
|
'GITEA_API_URL': self.api_url,
|
||||||
|
'GITEA_API_TOKEN': self.api_token,
|
||||||
|
'GITEA_OWNER': self.owner
|
||||||
|
}
|
||||||
|
|
||||||
|
missing = [key for key, value in required.items() if not value]
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
raise ValueError(
|
||||||
|
f"Missing required configuration: {', '.join(missing)}\n"
|
||||||
|
"Check your ~/.config/claude/gitea.env file"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp-servers/gitea/
|
||||||
|
├── .venv/ # Python virtual environment
|
||||||
|
├── requirements.txt # Python dependencies
|
||||||
|
├── .env.example # Configuration template
|
||||||
|
├── mcp_server/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── server.py # MCP server entry point
|
||||||
|
│ ├── config.py # Configuration loader
|
||||||
|
│ ├── gitea_client.py # Gitea API client
|
||||||
|
│ └── tools/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── issues.py # Issue CRUD tools
|
||||||
|
│ └── labels.py # Label management tools
|
||||||
|
└── tests/
|
||||||
|
├── test_config.py
|
||||||
|
├── test_gitea_client.py
|
||||||
|
└── test_tools.py
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
**File:** `mcp-servers/gitea/requirements.txt`
|
||||||
|
|
||||||
|
```txt
|
||||||
|
anthropic-sdk>=0.18.0 # MCP SDK
|
||||||
|
python-dotenv>=1.0.0 # Environment variable loading
|
||||||
|
requests>=2.31.0 # HTTP client for Gitea API
|
||||||
|
pydantic>=2.5.0 # Data validation
|
||||||
|
pytest>=7.4.3 # Testing framework
|
||||||
|
pytest-asyncio>=0.23.0 # Async testing support
|
||||||
|
```
|
||||||
|
|
||||||
|
**Installation:**
|
||||||
|
```bash
|
||||||
|
cd mcp-servers/gitea
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate # Linux/Mac
|
||||||
|
# or .venv\Scripts\activate # Windows
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gitea API Client
|
||||||
|
|
||||||
|
```python
|
||||||
|
# mcp-servers/gitea/mcp_server/gitea_client.py
|
||||||
|
import requests
|
||||||
|
from typing import List, Dict, Optional
|
||||||
|
from .config import GiteaConfig
|
||||||
|
|
||||||
|
class GiteaClient:
|
||||||
|
"""Client for interacting with Gitea API"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
config = GiteaConfig()
|
||||||
|
config_dict = config.load()
|
||||||
|
|
||||||
|
self.base_url = config_dict['api_url']
|
||||||
|
self.token = config_dict['api_token']
|
||||||
|
self.owner = config_dict['owner']
|
||||||
|
self.repo = config_dict.get('repo') # Optional for PMO
|
||||||
|
self.mode = config_dict['mode']
|
||||||
|
|
||||||
|
self.session = requests.Session()
|
||||||
|
self.session.headers.update({
|
||||||
|
'Authorization': f'token {self.token}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
})
|
||||||
|
|
||||||
|
def list_issues(
|
||||||
|
self,
|
||||||
|
state: str = 'open',
|
||||||
|
labels: Optional[List[str]] = None,
|
||||||
|
repo: Optional[str] = None
|
||||||
|
) -> List[Dict]:
|
||||||
|
"""
|
||||||
|
List issues from Gitea repository.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
state: Issue state (open, closed, all)
|
||||||
|
labels: Filter by labels
|
||||||
|
repo: Override configured repo (for PMO multi-repo)
|
||||||
|
"""
|
||||||
|
target_repo = repo or self.repo
|
||||||
|
if not target_repo:
|
||||||
|
raise ValueError("Repository not specified")
|
||||||
|
|
||||||
|
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues"
|
||||||
|
params = {'state': state}
|
||||||
|
|
||||||
|
if labels:
|
||||||
|
params['labels'] = ','.join(labels)
|
||||||
|
|
||||||
|
response = self.session.get(url, params=params)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_issue(
|
||||||
|
self,
|
||||||
|
issue_number: int,
|
||||||
|
repo: Optional[str] = None
|
||||||
|
) -> Dict:
|
||||||
|
"""Get specific issue details"""
|
||||||
|
target_repo = repo or self.repo
|
||||||
|
if not target_repo:
|
||||||
|
raise ValueError("Repository not specified")
|
||||||
|
|
||||||
|
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues/{issue_number}"
|
||||||
|
response = self.session.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def create_issue(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
body: str,
|
||||||
|
labels: Optional[List[str]] = None,
|
||||||
|
repo: Optional[str] = None
|
||||||
|
) -> Dict:
|
||||||
|
"""Create a new issue in Gitea"""
|
||||||
|
target_repo = repo or self.repo
|
||||||
|
if not target_repo:
|
||||||
|
raise ValueError("Repository not specified")
|
||||||
|
|
||||||
|
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues"
|
||||||
|
data = {
|
||||||
|
'title': title,
|
||||||
|
'body': body
|
||||||
|
}
|
||||||
|
|
||||||
|
if labels:
|
||||||
|
data['labels'] = labels
|
||||||
|
|
||||||
|
response = self.session.post(url, json=data)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def update_issue(
|
||||||
|
self,
|
||||||
|
issue_number: int,
|
||||||
|
title: Optional[str] = None,
|
||||||
|
body: Optional[str] = None,
|
||||||
|
state: Optional[str] = None,
|
||||||
|
labels: Optional[List[str]] = None,
|
||||||
|
repo: Optional[str] = None
|
||||||
|
) -> Dict:
|
||||||
|
"""Update existing issue"""
|
||||||
|
target_repo = repo or self.repo
|
||||||
|
if not target_repo:
|
||||||
|
raise ValueError("Repository not specified")
|
||||||
|
|
||||||
|
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues/{issue_number}"
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
if title is not None:
|
||||||
|
data['title'] = title
|
||||||
|
if body is not None:
|
||||||
|
data['body'] = body
|
||||||
|
if state is not None:
|
||||||
|
data['state'] = state
|
||||||
|
if labels is not None:
|
||||||
|
data['labels'] = labels
|
||||||
|
|
||||||
|
response = self.session.patch(url, json=data)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def add_comment(
|
||||||
|
self,
|
||||||
|
issue_number: int,
|
||||||
|
comment: str,
|
||||||
|
repo: Optional[str] = None
|
||||||
|
) -> Dict:
|
||||||
|
"""Add comment to issue"""
|
||||||
|
target_repo = repo or self.repo
|
||||||
|
if not target_repo:
|
||||||
|
raise ValueError("Repository not specified")
|
||||||
|
|
||||||
|
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues/{issue_number}/comments"
|
||||||
|
data = {'body': comment}
|
||||||
|
|
||||||
|
response = self.session.post(url, json=data)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_labels(
|
||||||
|
self,
|
||||||
|
repo: Optional[str] = None
|
||||||
|
) -> List[Dict]:
|
||||||
|
"""Get all labels from repository"""
|
||||||
|
target_repo = repo or self.repo
|
||||||
|
if not target_repo:
|
||||||
|
raise ValueError("Repository not specified")
|
||||||
|
|
||||||
|
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/labels"
|
||||||
|
response = self.session.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_org_labels(self) -> List[Dict]:
|
||||||
|
"""Get organization-level labels"""
|
||||||
|
url = f"{self.base_url}/orgs/{self.owner}/labels"
|
||||||
|
response = self.session.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
# PMO-specific methods
|
||||||
|
|
||||||
|
def list_repos(self) -> List[Dict]:
|
||||||
|
"""List all repositories in organization (PMO mode)"""
|
||||||
|
url = f"{self.base_url}/orgs/{self.owner}/repos"
|
||||||
|
response = self.session.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def aggregate_issues(
|
||||||
|
self,
|
||||||
|
state: str = 'open',
|
||||||
|
labels: Optional[List[str]] = None
|
||||||
|
) -> Dict[str, List[Dict]]:
|
||||||
|
"""
|
||||||
|
Fetch issues across all repositories (PMO mode).
|
||||||
|
Returns dict keyed by repository name.
|
||||||
|
"""
|
||||||
|
repos = self.list_repos()
|
||||||
|
aggregated = {}
|
||||||
|
|
||||||
|
for repo in repos:
|
||||||
|
repo_name = repo['name']
|
||||||
|
try:
|
||||||
|
issues = self.list_issues(
|
||||||
|
state=state,
|
||||||
|
labels=labels,
|
||||||
|
repo=repo_name
|
||||||
|
)
|
||||||
|
if issues:
|
||||||
|
aggregated[repo_name] = issues
|
||||||
|
except Exception as e:
|
||||||
|
# Log error but continue with other repos
|
||||||
|
print(f"Error fetching issues from {repo_name}: {e}")
|
||||||
|
|
||||||
|
return aggregated
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Label Taxonomy System
|
||||||
|
|
||||||
|
### 43-Label System
|
||||||
|
|
||||||
|
**Organization Labels (27):**
|
||||||
|
- Agent/2
|
||||||
|
- Complexity/3
|
||||||
|
- Efforts/5
|
||||||
|
- Priority/4
|
||||||
|
- Risk/3
|
||||||
|
- Source/4
|
||||||
|
- Type/6 (includes Type/Refactor)
|
||||||
|
|
||||||
|
**Repository Labels (16):**
|
||||||
|
- Component/9
|
||||||
|
- Tech/7
|
||||||
|
|
||||||
|
### Label Suggestion Logic
|
||||||
|
|
||||||
|
```python
|
||||||
|
# mcp-servers/gitea/mcp_server/tools/labels.py
|
||||||
|
from typing import List, Dict
|
||||||
|
import re
|
||||||
|
|
||||||
|
class LabelTools:
|
||||||
|
def __init__(self, gitea_client):
|
||||||
|
self.gitea = gitea_client
|
||||||
|
|
||||||
|
async def get_labels(self, repo: str = None) -> List[Dict]:
|
||||||
|
"""Get all labels (org + repo)"""
|
||||||
|
org_labels = self.gitea.get_org_labels()
|
||||||
|
|
||||||
|
if repo or self.gitea.repo:
|
||||||
|
target_repo = repo or self.gitea.repo
|
||||||
|
repo_labels = self.gitea.get_labels(target_repo)
|
||||||
|
return org_labels + repo_labels
|
||||||
|
|
||||||
|
return org_labels
|
||||||
|
|
||||||
|
async def suggest_labels(self, context: str) -> List[str]:
|
||||||
|
"""
|
||||||
|
Analyze context and suggest appropriate labels.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
context: Issue title + description or sprint context
|
||||||
|
"""
|
||||||
|
suggested = []
|
||||||
|
context_lower = context.lower()
|
||||||
|
|
||||||
|
# Type detection (exclusive - only one)
|
||||||
|
if any(word in context_lower for word in ['bug', 'error', 'fix', 'broken']):
|
||||||
|
suggested.append('Type/Bug')
|
||||||
|
elif any(word in context_lower for word in ['refactor', 'extract', 'restructure', 'architecture', 'service extraction']):
|
||||||
|
suggested.append('Type/Refactor')
|
||||||
|
elif any(word in context_lower for word in ['feature', 'add', 'implement', 'new']):
|
||||||
|
suggested.append('Type/Feature')
|
||||||
|
elif any(word in context_lower for word in ['docs', 'documentation', 'readme']):
|
||||||
|
suggested.append('Type/Documentation')
|
||||||
|
elif any(word in context_lower for word in ['test', 'testing', 'spec']):
|
||||||
|
suggested.append('Type/Test')
|
||||||
|
elif any(word in context_lower for word in ['chore', 'maintenance', 'update']):
|
||||||
|
suggested.append('Type/Chore')
|
||||||
|
|
||||||
|
# Priority detection
|
||||||
|
if any(word in context_lower for word in ['critical', 'urgent', 'blocker', 'blocking']):
|
||||||
|
suggested.append('Priority/Critical')
|
||||||
|
elif any(word in context_lower for word in ['high', 'important', 'asap']):
|
||||||
|
suggested.append('Priority/High')
|
||||||
|
elif any(word in context_lower for word in ['low', 'nice-to-have', 'optional']):
|
||||||
|
suggested.append('Priority/Low')
|
||||||
|
else:
|
||||||
|
suggested.append('Priority/Medium')
|
||||||
|
|
||||||
|
# Component detection (based on keywords)
|
||||||
|
component_keywords = {
|
||||||
|
'Component/Backend': ['backend', 'server', 'api', 'database', 'service'],
|
||||||
|
'Component/Frontend': ['frontend', 'ui', 'interface', 'react', 'vue'],
|
||||||
|
'Component/API': ['api', 'endpoint', 'rest', 'graphql'],
|
||||||
|
'Component/Database': ['database', 'db', 'sql', 'migration', 'schema'],
|
||||||
|
'Component/Auth': ['auth', 'authentication', 'login', 'oauth', 'token'],
|
||||||
|
'Component/Deploy': ['deploy', 'deployment', 'docker', 'kubernetes'],
|
||||||
|
'Component/Testing': ['test', 'testing', 'spec', 'jest', 'pytest'],
|
||||||
|
'Component/Docs': ['docs', 'documentation', 'readme', 'guide']
|
||||||
|
}
|
||||||
|
|
||||||
|
for label, keywords in component_keywords.items():
|
||||||
|
if any(keyword in context_lower for keyword in keywords):
|
||||||
|
suggested.append(label)
|
||||||
|
|
||||||
|
# Source detection (based on git branch or context)
|
||||||
|
if 'development' in context_lower or 'dev/' in context_lower:
|
||||||
|
suggested.append('Source/Development')
|
||||||
|
elif 'staging' in context_lower:
|
||||||
|
suggested.append('Source/Staging')
|
||||||
|
elif 'production' in context_lower or 'prod' in context_lower:
|
||||||
|
suggested.append('Source/Production')
|
||||||
|
|
||||||
|
return suggested
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MCP Tools
|
||||||
|
|
||||||
|
### Issue Tools
|
||||||
|
|
||||||
|
```python
|
||||||
|
# mcp-servers/gitea/mcp_server/tools/issues.py
|
||||||
|
class IssueTools:
|
||||||
|
def __init__(self, gitea_client):
|
||||||
|
self.gitea = gitea_client
|
||||||
|
|
||||||
|
async def list_issues(self, state='open', labels=None, repo=None):
|
||||||
|
"""List issues in repository"""
|
||||||
|
return self.gitea.list_issues(state=state, labels=labels, repo=repo)
|
||||||
|
|
||||||
|
async def get_issue(self, issue_number, repo=None):
|
||||||
|
"""Get specific issue details"""
|
||||||
|
return self.gitea.get_issue(issue_number, repo=repo)
|
||||||
|
|
||||||
|
async def create_issue(self, title, body, labels=None, repo=None):
|
||||||
|
"""Create new issue"""
|
||||||
|
return self.gitea.create_issue(title, body, labels=labels, repo=repo)
|
||||||
|
|
||||||
|
async def update_issue(self, issue_number, title=None, body=None, state=None, labels=None, repo=None):
|
||||||
|
"""Update existing issue"""
|
||||||
|
return self.gitea.update_issue(
|
||||||
|
issue_number,
|
||||||
|
title=title,
|
||||||
|
body=body,
|
||||||
|
state=state,
|
||||||
|
labels=labels,
|
||||||
|
repo=repo
|
||||||
|
)
|
||||||
|
|
||||||
|
async def add_comment(self, issue_number, comment, repo=None):
|
||||||
|
"""Add comment to issue"""
|
||||||
|
return self.gitea.add_comment(issue_number, comment, repo=repo)
|
||||||
|
|
||||||
|
# PMO-specific
|
||||||
|
async def aggregate_issues(self, state='open', labels=None):
|
||||||
|
"""Aggregate issues across all repositories (PMO mode)"""
|
||||||
|
if self.gitea.mode != 'company':
|
||||||
|
raise ValueError("aggregate_issues only available in company mode")
|
||||||
|
return self.gitea.aggregate_issues(state=state, labels=labels)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
|
||||||
|
```python
|
||||||
|
# tests/test_config.py
|
||||||
|
import pytest
|
||||||
|
from pathlib import Path
|
||||||
|
from mcp_server.config import GiteaConfig
|
||||||
|
|
||||||
|
def test_load_system_config(tmp_path, monkeypatch):
|
||||||
|
"""Test loading system-level configuration"""
|
||||||
|
# Mock home directory
|
||||||
|
config_dir = tmp_path / '.config' / 'claude'
|
||||||
|
config_dir.mkdir(parents=True)
|
||||||
|
|
||||||
|
config_file = config_dir / 'gitea.env'
|
||||||
|
config_file.write_text(
|
||||||
|
"GITEA_API_URL=https://test.com/api/v1\n"
|
||||||
|
"GITEA_API_TOKEN=test_token\n"
|
||||||
|
"GITEA_OWNER=test_owner\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setenv('HOME', str(tmp_path))
|
||||||
|
|
||||||
|
config = GiteaConfig()
|
||||||
|
result = config.load()
|
||||||
|
|
||||||
|
assert result['api_url'] == 'https://test.com/api/v1'
|
||||||
|
assert result['api_token'] == 'test_token'
|
||||||
|
assert result['owner'] == 'test_owner'
|
||||||
|
assert result['mode'] == 'company' # No repo specified
|
||||||
|
|
||||||
|
def test_project_config_override(tmp_path, monkeypatch):
|
||||||
|
"""Test that project config overrides system config"""
|
||||||
|
# Set up system config
|
||||||
|
system_config_dir = tmp_path / '.config' / 'claude'
|
||||||
|
system_config_dir.mkdir(parents=True)
|
||||||
|
|
||||||
|
system_config = system_config_dir / 'gitea.env'
|
||||||
|
system_config.write_text(
|
||||||
|
"GITEA_API_URL=https://test.com/api/v1\n"
|
||||||
|
"GITEA_API_TOKEN=test_token\n"
|
||||||
|
"GITEA_OWNER=test_owner\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set up project config
|
||||||
|
project_dir = tmp_path / 'project'
|
||||||
|
project_dir.mkdir()
|
||||||
|
|
||||||
|
project_config = project_dir / '.env'
|
||||||
|
project_config.write_text("GITEA_REPO=test_repo\n")
|
||||||
|
|
||||||
|
monkeypatch.setenv('HOME', str(tmp_path))
|
||||||
|
monkeypatch.chdir(project_dir)
|
||||||
|
|
||||||
|
config = GiteaConfig()
|
||||||
|
result = config.load()
|
||||||
|
|
||||||
|
assert result['repo'] == 'test_repo'
|
||||||
|
assert result['mode'] == 'project'
|
||||||
|
|
||||||
|
def test_missing_required_config():
|
||||||
|
"""Test error handling for missing configuration"""
|
||||||
|
with pytest.raises(FileNotFoundError):
|
||||||
|
config = GiteaConfig()
|
||||||
|
config.load()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
|
||||||
|
```python
|
||||||
|
# tests/test_gitea_client.py
|
||||||
|
import pytest
|
||||||
|
from mcp_server.gitea_client import GiteaClient
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def gitea_client():
|
||||||
|
"""Fixture providing configured Gitea client"""
|
||||||
|
return GiteaClient()
|
||||||
|
|
||||||
|
def test_list_issues(gitea_client):
|
||||||
|
"""Test listing issues from Gitea"""
|
||||||
|
issues = gitea_client.list_issues(state='open')
|
||||||
|
assert isinstance(issues, list)
|
||||||
|
|
||||||
|
def test_create_issue(gitea_client):
|
||||||
|
"""Test creating an issue in Gitea"""
|
||||||
|
issue = gitea_client.create_issue(
|
||||||
|
title="Test Issue",
|
||||||
|
body="Test body",
|
||||||
|
labels=["Type/Bug", "Priority/Low"]
|
||||||
|
)
|
||||||
|
assert issue['title'] == "Test Issue"
|
||||||
|
assert any(label['name'] == "Type/Bug" for label in issue['labels'])
|
||||||
|
|
||||||
|
def test_get_labels(gitea_client):
|
||||||
|
"""Test fetching labels"""
|
||||||
|
labels = gitea_client.get_labels()
|
||||||
|
assert isinstance(labels, list)
|
||||||
|
assert len(labels) > 0
|
||||||
|
|
||||||
|
def test_pmo_mode_aggregate_issues():
|
||||||
|
"""Test PMO mode aggregation (no repo specified)"""
|
||||||
|
# Set up client without repo
|
||||||
|
client = GiteaClient() # Should detect company mode
|
||||||
|
|
||||||
|
if client.mode == 'company':
|
||||||
|
aggregated = client.aggregate_issues(state='open')
|
||||||
|
assert isinstance(aggregated, dict)
|
||||||
|
# Each key should be a repo name
|
||||||
|
for repo_name, issues in aggregated.items():
|
||||||
|
assert isinstance(issues, list)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Activate virtual environment
|
||||||
|
source .venv/bin/activate
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
pytest
|
||||||
|
|
||||||
|
# Run with coverage
|
||||||
|
pytest --cov=mcp_server --cov-report=html
|
||||||
|
|
||||||
|
# Run specific test file
|
||||||
|
pytest tests/test_config.py
|
||||||
|
|
||||||
|
# Run with verbose output
|
||||||
|
pytest -v
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
### Caching
|
||||||
|
|
||||||
|
```python
|
||||||
|
from functools import lru_cache
|
||||||
|
|
||||||
|
@lru_cache(maxsize=128)
|
||||||
|
def get_labels_cached(self, repo: str) -> List[Dict]:
|
||||||
|
"""Cached label retrieval to reduce API calls"""
|
||||||
|
return self.get_labels(repo)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Retry Logic
|
||||||
|
|
||||||
|
```python
|
||||||
|
import time
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
def retry_on_failure(max_retries=3, delay=1):
|
||||||
|
"""Decorator for retrying failed API calls"""
|
||||||
|
def decorator(func: Callable):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
for attempt in range(max_retries):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
if attempt == max_retries - 1:
|
||||||
|
raise
|
||||||
|
time.sleep(delay * (attempt + 1))
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
@retry_on_failure(max_retries=3)
|
||||||
|
def list_issues(self, state='open', labels=None, repo=None):
|
||||||
|
"""List issues with automatic retry"""
|
||||||
|
# Implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**Issue:** Module not found
|
||||||
|
```bash
|
||||||
|
# Solution: Ensure PYTHONPATH is set in .mcp.json
|
||||||
|
"env": {
|
||||||
|
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Issue:** Configuration not loading
|
||||||
|
```bash
|
||||||
|
# Solution: Check file permissions
|
||||||
|
chmod 600 ~/.config/claude/gitea.env
|
||||||
|
|
||||||
|
# Verify file exists
|
||||||
|
cat ~/.config/claude/gitea.env
|
||||||
|
```
|
||||||
|
|
||||||
|
**Issue:** API authentication failing
|
||||||
|
```bash
|
||||||
|
# Solution: Test token manually
|
||||||
|
curl -H "Authorization: token YOUR_TOKEN" \
|
||||||
|
https://your-gitea.com/api/v1/user
|
||||||
|
```
|
||||||
|
|
||||||
|
**Issue:** PMO mode not working
|
||||||
|
```bash
|
||||||
|
# Solution: Ensure GITEA_REPO is NOT set
|
||||||
|
# Check environment variables
|
||||||
|
env | grep GITEA
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
1. **Token Storage:**
|
||||||
|
- Store tokens in `~/.config/claude/gitea.env`
|
||||||
|
- Set file permissions to 600
|
||||||
|
- Never commit tokens to git
|
||||||
|
|
||||||
|
2. **Input Validation:**
|
||||||
|
- Validate all user input before API calls
|
||||||
|
- Sanitize issue titles and descriptions
|
||||||
|
- Prevent injection attacks
|
||||||
|
|
||||||
|
3. **Error Handling:**
|
||||||
|
- Don't leak tokens in error messages
|
||||||
|
- Log errors without sensitive data
|
||||||
|
- Provide user-friendly error messages
|
||||||
|
|
||||||
|
4. **API Rate Limiting:**
|
||||||
|
- Implement exponential backoff
|
||||||
|
- Cache frequently accessed data
|
||||||
|
- Batch requests where possible
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. **Set up system configuration**
|
||||||
|
2. **Create virtual environment**
|
||||||
|
3. **Install dependencies**
|
||||||
|
4. **Run tests against actual Gitea instance**
|
||||||
|
5. **Integrate with projman plugin**
|
||||||
1295
docs/references/MCP-WIKIJS.md
Normal file
1295
docs/references/MCP-WIKIJS.md
Normal file
File diff suppressed because it is too large
Load Diff
902
docs/references/PLUGIN-PMO.md
Normal file
902
docs/references/PLUGIN-PMO.md
Normal file
@@ -0,0 +1,902 @@
|
|||||||
|
# PMO Plugin Reference (projman-pmo)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `projman-pmo` plugin provides multi-project PMO coordination with cross-project dependency tracking, resource allocation, and company-wide visibility. It builds on projman but operates at the organization level.
|
||||||
|
|
||||||
|
**Build Order:** Build AFTER projman is working and validated
|
||||||
|
**Target Users:** PMO coordinators, engineering managers, CTOs
|
||||||
|
**Scope:** Multi-project coordination across entire organization
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Cross-project status aggregation
|
||||||
|
- Dependency tracking and visualization
|
||||||
|
- Resource conflict detection
|
||||||
|
- Release coordination
|
||||||
|
- Company-wide lessons learned search
|
||||||
|
- Multi-project prioritization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Plugin Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
projman-pmo/
|
||||||
|
├── .claude-plugin/
|
||||||
|
│ └── plugin.json # Plugin manifest
|
||||||
|
├── .mcp.json # Points to ../mcp-servers/ (company mode)
|
||||||
|
├── commands/
|
||||||
|
│ ├── pmo-status.md # Multi-project status overview
|
||||||
|
│ ├── pmo-priorities.md # Cross-project prioritization
|
||||||
|
│ ├── pmo-dependencies.md # Dependency visualization
|
||||||
|
│ ├── pmo-conflicts.md # Resource conflict detection
|
||||||
|
│ └── pmo-schedule.md # Deployment schedule coordination
|
||||||
|
├── agents/
|
||||||
|
│ └── pmo-coordinator.md # Multi-project coordination agent
|
||||||
|
└── README.md # Installation and usage guide
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Plugin .mcp.json
|
||||||
|
|
||||||
|
**File:** `projman-pmo/.mcp.json`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"gitea-pmo": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "mcp_server.server"],
|
||||||
|
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
||||||
|
"env": {
|
||||||
|
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
||||||
|
"GITEA_API_URL": "${GITEA_API_URL}",
|
||||||
|
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
||||||
|
"GITEA_OWNER": "${GITEA_OWNER}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wikijs-pmo": {
|
||||||
|
"command": "python",
|
||||||
|
"args": ["-m", "mcp_server.server"],
|
||||||
|
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
||||||
|
"env": {
|
||||||
|
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
||||||
|
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
||||||
|
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
||||||
|
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critical Differences from projman:**
|
||||||
|
- **NO** `GITEA_REPO` → operates on all repositories
|
||||||
|
- **NO** `WIKIJS_PROJECT` → operates on entire `/hyper-hive-labs` namespace
|
||||||
|
- Same shared MCP servers at `../mcp-servers/`
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
**Required (System-Level Only):**
|
||||||
|
- `GITEA_API_URL`
|
||||||
|
- `GITEA_API_TOKEN`
|
||||||
|
- `GITEA_OWNER`
|
||||||
|
- `WIKIJS_API_URL`
|
||||||
|
- `WIKIJS_API_TOKEN`
|
||||||
|
- `WIKIJS_BASE_PATH`
|
||||||
|
|
||||||
|
**NOT Required:**
|
||||||
|
- `GITEA_REPO` - PMO operates across all repos
|
||||||
|
- `WIKIJS_PROJECT` - PMO operates across entire namespace
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PMO Coordinator Agent
|
||||||
|
|
||||||
|
**File:** `agents/pmo-coordinator.md`
|
||||||
|
|
||||||
|
### Agent Personality
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
You are the PMO Coordinator for Hyper Hive Labs.
|
||||||
|
|
||||||
|
Your role:
|
||||||
|
- Maintain strategic view across all projects
|
||||||
|
- Identify cross-project dependencies
|
||||||
|
- Detect resource conflicts
|
||||||
|
- Balance competing priorities
|
||||||
|
- Coordinate release timing
|
||||||
|
- Track customer deployment schedules
|
||||||
|
- Surface company-wide lessons learned
|
||||||
|
|
||||||
|
You are:
|
||||||
|
- Strategic thinker
|
||||||
|
- Dependency-aware
|
||||||
|
- Conflict detector
|
||||||
|
- Priority balancer
|
||||||
|
- Team coordinator
|
||||||
|
- NOT a micromanager
|
||||||
|
|
||||||
|
You delegate to project-level agents:
|
||||||
|
- Don't micromanage single projects
|
||||||
|
- Focus on cross-project issues
|
||||||
|
- Surface conflicts early
|
||||||
|
- Facilitate coordination
|
||||||
|
- Provide strategic guidance
|
||||||
|
|
||||||
|
Available Tools:
|
||||||
|
- aggregate_issues: Fetch issues across all repositories
|
||||||
|
- search_all_projects: Search lessons across all projects
|
||||||
|
- list_repos: Get all organization repositories
|
||||||
|
- get_shared_docs: Access company-wide patterns and best practices
|
||||||
|
|
||||||
|
Key Principles:
|
||||||
|
1. Strategic overview, not tactical details
|
||||||
|
2. Cross-project coordination, not single-project management
|
||||||
|
3. Identify conflicts before they become problems
|
||||||
|
4. Balance competing priorities across teams
|
||||||
|
5. Learn from patterns across all projects
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delegation Model
|
||||||
|
|
||||||
|
```
|
||||||
|
PMO Agent (projman-pmo)
|
||||||
|
├─ Identifies cross-project issues
|
||||||
|
├─ Detects resource conflicts
|
||||||
|
├─ Coordinates release timing
|
||||||
|
└─ Delegates to...
|
||||||
|
├─ Planner Agent (projman) → for project planning
|
||||||
|
├─ Orchestrator Agent (projman) → for project execution
|
||||||
|
└─ Executor Agent (projman) → for implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
User: /pmo-status
|
||||||
|
|
||||||
|
PMO: Projects Overview:
|
||||||
|
|
||||||
|
CuisineFlow: Sprint in progress, 60% complete
|
||||||
|
└─ Blocking: CuisineFlow-Site deployment
|
||||||
|
|
||||||
|
I notice CuisineFlow-Site is waiting on API changes.
|
||||||
|
Use projman in the cuisineflow-site repo to plan the sync work.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### 1. PMO Status Command
|
||||||
|
|
||||||
|
**File:** `commands/pmo-status.md`
|
||||||
|
|
||||||
|
**Usage:** `/pmo-status`
|
||||||
|
|
||||||
|
**Description:** Consolidated view of all active projects
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-status
|
||||||
|
|
||||||
|
PMO: Projects Overview
|
||||||
|
================
|
||||||
|
|
||||||
|
CuisineFlow (main product)
|
||||||
|
├── Sprint: Intuit Engine Extraction
|
||||||
|
├── Status: In Progress (60%)
|
||||||
|
├── Issue: #47
|
||||||
|
├── Blockers: None
|
||||||
|
├── Next: API testing
|
||||||
|
└── Timeline: On track (1 week remaining)
|
||||||
|
|
||||||
|
CuisineFlow-Site (demo)
|
||||||
|
├── Sprint: Dashboard Updates
|
||||||
|
├── Status: Waiting on dependencies
|
||||||
|
├── Issue: #12
|
||||||
|
├── Blockers: Depends on CuisineFlow #47 (API changes)
|
||||||
|
├── Next: Deploy when API ready
|
||||||
|
└── Timeline: Blocked (waiting on CuisineFlow)
|
||||||
|
|
||||||
|
Intuit-Engine (service)
|
||||||
|
├── Sprint: Initial Setup
|
||||||
|
├── Status: Planning
|
||||||
|
├── Issue: #3
|
||||||
|
├── Blockers: Architecture decisions needed
|
||||||
|
├── Next: Service boundary definition
|
||||||
|
└── Timeline: Not started
|
||||||
|
|
||||||
|
HHL-Site (marketing)
|
||||||
|
├── Sprint: Content Updates
|
||||||
|
├── Status: Complete
|
||||||
|
├── Issue: #8 (closed)
|
||||||
|
├── Blockers: None
|
||||||
|
├── Next: Deploy to production
|
||||||
|
└── Timeline: Ready for deployment
|
||||||
|
|
||||||
|
Cross-Project Insights:
|
||||||
|
- CuisineFlow-Site blocked by CuisineFlow #47
|
||||||
|
- Intuit-Engine needs architectural guidance
|
||||||
|
- HHL-Site ready for deployment
|
||||||
|
|
||||||
|
Suggested Actions:
|
||||||
|
1. Prioritize CuisineFlow #47 completion (unblocks Site)
|
||||||
|
2. Schedule architecture review for Intuit-Engine
|
||||||
|
3. Deploy HHL-Site content updates
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Shows all active projects
|
||||||
|
- Identifies blockers
|
||||||
|
- Surfaces dependencies
|
||||||
|
- Provides actionable insights
|
||||||
|
|
||||||
|
### 2. PMO Priorities Command
|
||||||
|
|
||||||
|
**File:** `commands/pmo-priorities.md`
|
||||||
|
|
||||||
|
**Usage:** `/pmo-priorities`
|
||||||
|
|
||||||
|
**Description:** Review and adjust priorities across projects
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-priorities
|
||||||
|
|
||||||
|
PMO: Priority Analysis Across Projects
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Critical (Blocks launches):
|
||||||
|
1. CuisineFlow #47 - Intuit Engine Extraction
|
||||||
|
→ Blocks: CuisineFlow v2.0 launch (Nov 15)
|
||||||
|
→ Blocks: CuisineFlow-Site deployment
|
||||||
|
→ Status: 60% complete, 1 week remaining
|
||||||
|
→ Recommendation: Maintain focus
|
||||||
|
|
||||||
|
High (Important features):
|
||||||
|
2. CuisineFlow-Site #12 - Dashboard Updates
|
||||||
|
→ Depends on: CuisineFlow #47
|
||||||
|
→ Status: Waiting
|
||||||
|
→ Recommendation: Begin planning, wait for #47
|
||||||
|
|
||||||
|
3. Intuit-Engine #3 - Initial Setup
|
||||||
|
→ Enables: Service architecture
|
||||||
|
→ Status: Planning phase
|
||||||
|
→ Recommendation: Schedule architecture review
|
||||||
|
|
||||||
|
Medium (Enhancements):
|
||||||
|
4. HHL-Site #8 - Content Updates
|
||||||
|
→ Status: Complete, ready to deploy
|
||||||
|
→ Recommendation: Deploy this week
|
||||||
|
|
||||||
|
Resource Analysis:
|
||||||
|
Leo (primary developer):
|
||||||
|
- Working on: CuisineFlow #47 (Critical)
|
||||||
|
- Next: CuisineFlow-Site #12 (High)
|
||||||
|
- Later: Intuit-Engine #3 (High)
|
||||||
|
|
||||||
|
⚠️ Potential Conflict:
|
||||||
|
Leo is assigned to 3 high-priority items. Consider:
|
||||||
|
- Maintaining focus on #47 (blocks launch)
|
||||||
|
- Queueing #12 for after #47 completion
|
||||||
|
- Scheduling #3 architecture review with team
|
||||||
|
|
||||||
|
Recommend any priority changes?
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Clear priority ranking
|
||||||
|
- Resource allocation visibility
|
||||||
|
- Conflict identification
|
||||||
|
- Actionable recommendations
|
||||||
|
|
||||||
|
### 3. PMO Dependencies Command
|
||||||
|
|
||||||
|
**File:** `commands/pmo-dependencies.md`
|
||||||
|
|
||||||
|
**Usage:** `/pmo-dependencies`
|
||||||
|
|
||||||
|
**Description:** Visualize and manage project dependencies
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-dependencies
|
||||||
|
|
||||||
|
PMO: Project Dependencies
|
||||||
|
====================
|
||||||
|
|
||||||
|
Dependency Graph:
|
||||||
|
|
||||||
|
Intuit-Engine (service)
|
||||||
|
↓ (must complete before)
|
||||||
|
CuisineFlow (main)
|
||||||
|
↓ (API changes required by)
|
||||||
|
CuisineFlow-Site (demo)
|
||||||
|
↓ (deploy together)
|
||||||
|
Customer VPS (deployments)
|
||||||
|
|
||||||
|
Detailed Dependencies:
|
||||||
|
|
||||||
|
1. CuisineFlow → Intuit-Engine
|
||||||
|
Type: Service extraction
|
||||||
|
Status: In progress
|
||||||
|
Blocker: Must complete #47 before v2.0 launch
|
||||||
|
Impact: High (blocks launch)
|
||||||
|
|
||||||
|
2. CuisineFlow → CuisineFlow-Site
|
||||||
|
Type: Feature sync
|
||||||
|
Status: Waiting
|
||||||
|
Blocker: Dashboard updates need API changes from #47
|
||||||
|
Impact: Medium (demo consistency)
|
||||||
|
|
||||||
|
3. CuisineFlow → Customer VPS
|
||||||
|
Type: Deployment
|
||||||
|
Status: Pending
|
||||||
|
Blocker: v2.0 launch must complete before customer updates
|
||||||
|
Impact: High (customer commitments)
|
||||||
|
|
||||||
|
Deployment Order:
|
||||||
|
1. Complete Intuit-Engine service extraction
|
||||||
|
2. Deploy CuisineFlow v2.0 to production
|
||||||
|
3. Sync CuisineFlow-Site demo
|
||||||
|
4. Update customer VPS instances
|
||||||
|
|
||||||
|
Critical Path:
|
||||||
|
Intuit-Engine (#3) → CuisineFlow (#47) → Site (#12) → Customer VPS
|
||||||
|
Estimated timeline: 3 weeks total
|
||||||
|
|
||||||
|
Risks:
|
||||||
|
- CuisineFlow #47 delay would cascade to all downstream
|
||||||
|
- Customer VPS updates have Nov 20 deadline
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Dependencies clearly visualized
|
||||||
|
- Critical path identified
|
||||||
|
- Deployment order defined
|
||||||
|
- Risks highlighted
|
||||||
|
|
||||||
|
### 4. PMO Conflicts Command
|
||||||
|
|
||||||
|
**File:** `commands/pmo-conflicts.md`
|
||||||
|
|
||||||
|
**Usage:** `/pmo-conflicts`
|
||||||
|
|
||||||
|
**Description:** Detect and resolve resource conflicts
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-conflicts
|
||||||
|
|
||||||
|
PMO: Resource Conflict Analysis
|
||||||
|
==========================
|
||||||
|
|
||||||
|
⚠️ Resource Conflict Detected
|
||||||
|
|
||||||
|
Leo (Developer):
|
||||||
|
Assigned to:
|
||||||
|
- CuisineFlow #47: Intuit Engine extraction (Priority: Critical)
|
||||||
|
- CuisineFlow-Site #12: Dashboard redesign (Priority: High)
|
||||||
|
- HHL-Site #8: Content update (Priority: Medium)
|
||||||
|
- Intuit-Engine #3: Service setup (Priority: High)
|
||||||
|
|
||||||
|
Conflict Analysis:
|
||||||
|
- 4 active assignments across 3 projects
|
||||||
|
- 2 are high priority or above
|
||||||
|
- Estimated total effort: 4 weeks
|
||||||
|
- Timeline: 2 weeks available
|
||||||
|
|
||||||
|
Recommendations:
|
||||||
|
1. FOCUS: CuisineFlow #47 (Critical, blocks launch)
|
||||||
|
→ Keep as primary focus
|
||||||
|
→ Estimated completion: 1 week
|
||||||
|
|
||||||
|
2. QUEUE: CuisineFlow-Site #12 (High, depends on #47)
|
||||||
|
→ Start after #47 completes
|
||||||
|
→ Natural sequencing
|
||||||
|
|
||||||
|
3. DELEGATE: HHL-Site #8 (Medium, content work)
|
||||||
|
→ Can be handled by marketing team
|
||||||
|
→ Low technical complexity
|
||||||
|
|
||||||
|
4. SCHEDULE: Intuit-Engine #3 (High, planning phase)
|
||||||
|
→ Schedule architecture review session
|
||||||
|
→ Team collaboration, not solo work
|
||||||
|
|
||||||
|
Timeline Conflict:
|
||||||
|
|
||||||
|
Without changes:
|
||||||
|
Week 1-2: CuisineFlow #47
|
||||||
|
Week 3-4: Site #12 + Engine #3 (CONFLICT)
|
||||||
|
|
||||||
|
With recommendations:
|
||||||
|
Week 1-2: CuisineFlow #47 (FOCUS)
|
||||||
|
Week 3: CuisineFlow-Site #12 (QUEUE)
|
||||||
|
Week 4: Intuit-Engine #3 (SCHEDULE)
|
||||||
|
HHL-Site #8: Marketing (DELEGATE)
|
||||||
|
|
||||||
|
Apply recommendations?
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Conflicts identified automatically
|
||||||
|
- Clear impact analysis
|
||||||
|
- Actionable recommendations
|
||||||
|
- Timeline visualization
|
||||||
|
|
||||||
|
### 5. PMO Schedule Command
|
||||||
|
|
||||||
|
**File:** `commands/pmo-schedule.md`
|
||||||
|
|
||||||
|
**Usage:** `/pmo-schedule`
|
||||||
|
|
||||||
|
**Description:** Coordinate deployment schedules
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-schedule
|
||||||
|
|
||||||
|
PMO: Deployment Schedule
|
||||||
|
===================
|
||||||
|
|
||||||
|
Week of Nov 6:
|
||||||
|
- CuisineFlow: Continue Sprint #47 (Intuit Engine)
|
||||||
|
- HHL-Site: Deploy content updates (#8) ✅
|
||||||
|
|
||||||
|
Week of Nov 13:
|
||||||
|
- CuisineFlow: Complete Sprint #47 ⚠️
|
||||||
|
→ Critical: Must complete by Nov 15 for launch
|
||||||
|
- CuisineFlow-Site: Begin Dashboard updates (#12)
|
||||||
|
|
||||||
|
Week of Nov 20:
|
||||||
|
- CuisineFlow: Deploy v2.0 to production 🚀
|
||||||
|
→ Deployment window: Nov 20-22
|
||||||
|
- CuisineFlow-Site: Sync demo with v2.0
|
||||||
|
- Customer VPS: Begin rollout (Deadline: Nov 20)
|
||||||
|
|
||||||
|
Week of Nov 27:
|
||||||
|
- Customer VPS: Continue rollout
|
||||||
|
- Intuit-Engine: Begin service implementation (#3)
|
||||||
|
|
||||||
|
Critical Dates:
|
||||||
|
- Nov 15: CuisineFlow v2.0 feature freeze
|
||||||
|
- Nov 20: Production deployment
|
||||||
|
- Nov 20: Customer VPS deadline
|
||||||
|
- Nov 22: Demo site sync
|
||||||
|
|
||||||
|
Dependencies:
|
||||||
|
✅ Intuit-Engine service boundaries defined
|
||||||
|
🔄 CuisineFlow #47 in progress (60%)
|
||||||
|
⏳ CuisineFlow-Site #12 waiting
|
||||||
|
⏳ Customer VPS rollout pending
|
||||||
|
|
||||||
|
Risks:
|
||||||
|
⚠️ CuisineFlow #47 delay would impact:
|
||||||
|
- v2.0 launch date (Nov 20)
|
||||||
|
- Customer VPS deadline (Nov 20)
|
||||||
|
- Demo site sync (Nov 22)
|
||||||
|
|
||||||
|
Mitigation:
|
||||||
|
- Monitor #47 progress daily
|
||||||
|
- Prepare rollback plan for customer VPS
|
||||||
|
- Communicate delays early if detected
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Clear timeline visibility
|
||||||
|
- Dependencies tracked
|
||||||
|
- Critical dates highlighted
|
||||||
|
- Risk mitigation planned
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Multi-Project Coordination Workflows
|
||||||
|
|
||||||
|
### Cross-Project Lessons Learned
|
||||||
|
|
||||||
|
```
|
||||||
|
User: Search for lessons about service extraction across all projects
|
||||||
|
|
||||||
|
PMO: Searching lessons across all projects...
|
||||||
|
|
||||||
|
Found 5 relevant lessons:
|
||||||
|
|
||||||
|
CuisineFlow:
|
||||||
|
- Sprint 08: Service boundary issues with shared DB
|
||||||
|
Tags: #service-extraction #database #refactoring
|
||||||
|
Key: Define boundaries at data model level first
|
||||||
|
|
||||||
|
- Sprint 12: API versioning during extraction
|
||||||
|
Tags: #api #versioning #refactoring
|
||||||
|
Key: Version APIs from the start
|
||||||
|
|
||||||
|
Intuit-Engine:
|
||||||
|
- Sprint 02: Circular dependencies in service init
|
||||||
|
Tags: #service-extraction #dependencies
|
||||||
|
Key: Watch for import cycles
|
||||||
|
|
||||||
|
CuisineFlow-Site:
|
||||||
|
- Sprint 05: Sync issues during backend refactor
|
||||||
|
Tags: #sync #refactoring
|
||||||
|
Key: Coordinate deployments during major changes
|
||||||
|
|
||||||
|
Shared Patterns:
|
||||||
|
- /hyper-hive-labs/shared/architecture-patterns/service-extraction
|
||||||
|
Key: Service Extraction Playbook
|
||||||
|
|
||||||
|
Common Themes:
|
||||||
|
1. Data model boundaries are critical
|
||||||
|
2. API versioning prevents integration issues
|
||||||
|
3. Watch for circular dependencies
|
||||||
|
4. Coordinate deployments during refactors
|
||||||
|
|
||||||
|
Apply these insights to current Intuit Engine extraction?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resource Allocation
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-status
|
||||||
|
|
||||||
|
PMO: [Shows status]
|
||||||
|
|
||||||
|
Resource Analysis:
|
||||||
|
- Leo: 3 active projects (CuisineFlow, Site, Engine)
|
||||||
|
- Marketing: 1 project (HHL-Site)
|
||||||
|
|
||||||
|
Bottleneck detected: Leo is on critical path for all technical work
|
||||||
|
|
||||||
|
Recommendations:
|
||||||
|
1. Prioritize work that unblocks others
|
||||||
|
2. Consider hiring/contracting for parallel work
|
||||||
|
3. Delegate non-critical work (HHL-Site content)
|
||||||
|
|
||||||
|
Would you like a detailed resource allocation report?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Release Coordination
|
||||||
|
|
||||||
|
```
|
||||||
|
User: Plan the v2.0 release across all affected projects
|
||||||
|
|
||||||
|
PMO: Release Coordination: CuisineFlow v2.0
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Affected Projects:
|
||||||
|
1. CuisineFlow (main product)
|
||||||
|
2. Intuit-Engine (new service)
|
||||||
|
3. CuisineFlow-Site (demo)
|
||||||
|
4. Customer VPS instances
|
||||||
|
|
||||||
|
Pre-Release Checklist:
|
||||||
|
✅ Intuit-Engine service deployed
|
||||||
|
🔄 CuisineFlow #47 complete (60%)
|
||||||
|
⏳ Integration tests pending
|
||||||
|
⏳ Demo site updates pending
|
||||||
|
⏳ Customer migration scripts ready
|
||||||
|
|
||||||
|
Deployment Sequence:
|
||||||
|
1. Deploy Intuit-Engine service (backend)
|
||||||
|
→ Date: Nov 18
|
||||||
|
→ Duration: 2 hours
|
||||||
|
→ Rollback plan: Ready
|
||||||
|
|
||||||
|
2. Deploy CuisineFlow v2.0 (main app)
|
||||||
|
→ Date: Nov 20
|
||||||
|
→ Duration: 4 hours
|
||||||
|
→ Rollback plan: Ready
|
||||||
|
|
||||||
|
3. Sync CuisineFlow-Site (demo)
|
||||||
|
→ Date: Nov 22
|
||||||
|
→ Duration: 1 hour
|
||||||
|
→ Dependencies: Step 2 complete
|
||||||
|
|
||||||
|
4. Update Customer VPS (production instances)
|
||||||
|
→ Date: Nov 23-25
|
||||||
|
→ Duration: Phased rollout
|
||||||
|
→ Dependencies: Steps 2 and 3 complete
|
||||||
|
|
||||||
|
Communication Plan:
|
||||||
|
- Nov 15: Feature freeze announcement
|
||||||
|
- Nov 19: Deployment notification
|
||||||
|
- Nov 20: v2.0 launch announcement
|
||||||
|
- Nov 25: Completion report
|
||||||
|
|
||||||
|
Risks & Mitigation:
|
||||||
|
- Risk: #47 completion delayed
|
||||||
|
Mitigation: Daily progress checks, adjust timeline early
|
||||||
|
|
||||||
|
- Risk: Integration issues during deployment
|
||||||
|
Mitigation: Comprehensive testing, rollback plan ready
|
||||||
|
|
||||||
|
- Risk: Customer VPS migration issues
|
||||||
|
Mitigation: Phased rollout, support on standby
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Company-Wide Patterns
|
||||||
|
|
||||||
|
### Accessing Shared Documentation
|
||||||
|
|
||||||
|
```python
|
||||||
|
# PMO agent can access company-wide patterns
|
||||||
|
shared_patterns = await wikijs.get_shared_docs("architecture-patterns")
|
||||||
|
|
||||||
|
# Returns:
|
||||||
|
# - microservices.md
|
||||||
|
# - api-gateway.md
|
||||||
|
# - database-per-service.md
|
||||||
|
# - service-extraction.md (created from lessons learned)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Shared Patterns
|
||||||
|
|
||||||
|
```
|
||||||
|
User: Create a shared pattern document for service extraction
|
||||||
|
|
||||||
|
PMO: I'll create a pattern document based on lessons from:
|
||||||
|
- CuisineFlow Sprint 08
|
||||||
|
- CuisineFlow Sprint 12
|
||||||
|
- Intuit-Engine Sprint 02
|
||||||
|
|
||||||
|
Creating: /hyper-hive-labs/shared/architecture-patterns/service-extraction
|
||||||
|
|
||||||
|
Service Extraction Pattern
|
||||||
|
=========================
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
- Extracting microservice from monolith
|
||||||
|
- Creating separate deployable service
|
||||||
|
- Isolating domain boundaries
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- Clear service boundaries defined
|
||||||
|
- Data model dependencies mapped
|
||||||
|
- API contracts specified
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
1. Define service boundaries at data model level
|
||||||
|
2. Design and version APIs first
|
||||||
|
3. Extract data layer with foreign key awareness
|
||||||
|
4. Implement service logic
|
||||||
|
5. Update integration points
|
||||||
|
6. Deploy and test
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
- Not defining boundaries at data level first
|
||||||
|
- Missing API versioning
|
||||||
|
- Circular dependencies in initialization
|
||||||
|
- Uncoordinated deployments
|
||||||
|
|
||||||
|
## Lessons Learned
|
||||||
|
[Links to specific sprint lessons]
|
||||||
|
|
||||||
|
Created ✅
|
||||||
|
Tags: #service-extraction #microservices #refactoring #architecture
|
||||||
|
|
||||||
|
This pattern is now available to all projects.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Phases
|
||||||
|
|
||||||
|
### Phase 9: PMO Plugin Foundation
|
||||||
|
|
||||||
|
**Deliverable:** PMO plugin requirements and design
|
||||||
|
|
||||||
|
**Tasks:**
|
||||||
|
1. Analyze multi-project workflows
|
||||||
|
2. Identify coordination pain points
|
||||||
|
3. Design PMO agent scope
|
||||||
|
4. Extend MCP server for multi-repo operations
|
||||||
|
5. Define delegation model
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Clear PMO plugin scope
|
||||||
|
- Multi-repo queries working
|
||||||
|
- Delegation model defined
|
||||||
|
- Doesn't duplicate projman functionality
|
||||||
|
|
||||||
|
### Phase 10: PMO Commands & Workflows
|
||||||
|
|
||||||
|
**Deliverable:** PMO-specific commands working
|
||||||
|
|
||||||
|
**Tasks:**
|
||||||
|
1. Implement `/pmo-status` command
|
||||||
|
2. Implement `/pmo-priorities` command
|
||||||
|
3. Implement `/pmo-dependencies` command
|
||||||
|
4. Implement `/pmo-conflicts` command
|
||||||
|
5. Implement `/pmo-schedule` command
|
||||||
|
6. Build conflict detection logic
|
||||||
|
7. Create dependency visualization
|
||||||
|
8. Design release coordination workflow
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- All commands provide valuable insights
|
||||||
|
- Dependencies clearly visualized
|
||||||
|
- Conflicts easily identified
|
||||||
|
- Coordination reduces manual overhead
|
||||||
|
|
||||||
|
### Phase 11: PMO Testing & Integration
|
||||||
|
|
||||||
|
**Deliverable:** Validated PMO plugin integrated with projman
|
||||||
|
|
||||||
|
**Tasks:**
|
||||||
|
1. Test with multiple projects (CuisineFlow, Site, Engine, HHL-Site)
|
||||||
|
2. Simulate deployment coordination scenarios
|
||||||
|
3. Test priority conflict resolution
|
||||||
|
4. Validate dependency tracking
|
||||||
|
5. Test cross-project lessons search
|
||||||
|
6. Ensure PMO delegates to projman agents
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Handles multiple projects correctly
|
||||||
|
- Dependencies respected
|
||||||
|
- Conflicts detected and surfaced
|
||||||
|
- Seamless integration with projman
|
||||||
|
- Cross-project lessons accessible
|
||||||
|
|
||||||
|
### Phase 12: Production Deployment
|
||||||
|
|
||||||
|
**Deliverable:** PMO plugin deployed and operational
|
||||||
|
|
||||||
|
**Tasks:**
|
||||||
|
1. Deploy across all environments (laptop, staging, production)
|
||||||
|
2. Configure for company-wide access
|
||||||
|
3. Set up backup and recovery
|
||||||
|
4. Establish monitoring and maintenance
|
||||||
|
5. Train team on PMO capabilities
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Works in all environments
|
||||||
|
- Configuration portable
|
||||||
|
- Backup procedures documented
|
||||||
|
- Team trained and comfortable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PMO vs Projman: Key Differences
|
||||||
|
|
||||||
|
| Aspect | projman | projman-pmo |
|
||||||
|
|--------|---------|-------------|
|
||||||
|
| **Scope** | Single repository | All repositories |
|
||||||
|
| **Configuration** | `GITEA_REPO` + `WIKIJS_PROJECT` | Neither (company-wide) |
|
||||||
|
| **Agents** | Planner, Orchestrator, Executor | PMO Coordinator |
|
||||||
|
| **Commands** | Sprint-focused | Cross-project coordination |
|
||||||
|
| **Gitea Access** | Single repo issues | All repos issues |
|
||||||
|
| **Wiki.js Access** | Project path | Entire namespace |
|
||||||
|
| **Primary User** | Developer, Team Lead | PMO, Manager, CTO |
|
||||||
|
| **Focus** | Tactical execution | Strategic coordination |
|
||||||
|
| **Delegation** | N/A | Delegates to projman |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Example 1: Detecting Blocked Work
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-status
|
||||||
|
|
||||||
|
PMO: CuisineFlow-Site: Waiting on dependencies
|
||||||
|
Blocked by: CuisineFlow #47 (API changes)
|
||||||
|
|
||||||
|
Recommendation: Focus resources on CuisineFlow #47 to unblock Site work
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Resource Conflict Resolution
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-conflicts
|
||||||
|
|
||||||
|
PMO: Leo assigned to 4 tasks across 3 projects
|
||||||
|
Estimated: 4 weeks work in 2 weeks timeline
|
||||||
|
|
||||||
|
Recommendations:
|
||||||
|
- Maintain focus on Critical priority (CuisineFlow #47)
|
||||||
|
- Delegate content work (HHL-Site #8) to marketing
|
||||||
|
- Schedule architectural review (Intuit-Engine #3) as team session
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Release Planning
|
||||||
|
|
||||||
|
```
|
||||||
|
User: /pmo-schedule
|
||||||
|
|
||||||
|
PMO: Critical Path: Engine → CuisineFlow → Site → Customer VPS
|
||||||
|
Deadline: Nov 20 (Customer VPS commitment)
|
||||||
|
|
||||||
|
Current: Week 1 of 3
|
||||||
|
Status: On track
|
||||||
|
|
||||||
|
Risk: If CuisineFlow #47 delayed, entire timeline at risk
|
||||||
|
Mitigation: Daily progress monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Use PMO for Strategic View
|
||||||
|
|
||||||
|
- Don't micromanage individual projects
|
||||||
|
- Focus on cross-project issues
|
||||||
|
- Identify blockers and dependencies
|
||||||
|
- Balance competing priorities
|
||||||
|
|
||||||
|
### 2. Delegate to Projman
|
||||||
|
|
||||||
|
- Use projman for project-specific planning
|
||||||
|
- Let project teams handle tactical execution
|
||||||
|
- PMO provides coordination, not implementation
|
||||||
|
|
||||||
|
### 3. Monitor Critical Path
|
||||||
|
|
||||||
|
- Identify which work blocks others
|
||||||
|
- Focus resources on critical path items
|
||||||
|
- Communicate delays early
|
||||||
|
|
||||||
|
### 4. Learn Across Projects
|
||||||
|
|
||||||
|
- Search lessons across all projects
|
||||||
|
- Create shared patterns from common themes
|
||||||
|
- Build company-wide knowledge base
|
||||||
|
|
||||||
|
### 5. Coordinate Releases
|
||||||
|
|
||||||
|
- Plan deployments across dependent projects
|
||||||
|
- Communicate timelines clearly
|
||||||
|
- Have rollback plans ready
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Issue: PMO showing wrong mode
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
```bash
|
||||||
|
# Ensure GITEA_REPO and WIKIJS_PROJECT are NOT set
|
||||||
|
env | grep GITEA
|
||||||
|
env | grep WIKIJS
|
||||||
|
|
||||||
|
# Should only show:
|
||||||
|
# GITEA_API_URL, GITEA_API_TOKEN, GITEA_OWNER
|
||||||
|
# WIKIJS_API_URL, WIKIJS_API_TOKEN, WIKIJS_BASE_PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Can't access all repositories
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Verify API token has organization-level access
|
||||||
|
- Check token permissions in Gitea
|
||||||
|
- Ensure GITEA_OWNER is correct
|
||||||
|
|
||||||
|
### Issue: Cross-project search not working
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Verify Wiki.js structure exists
|
||||||
|
- Check base path is correct
|
||||||
|
- Ensure projects have lessons-learned directories
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. **Complete projman plugin** (Phases 1-8)
|
||||||
|
2. **Validate projman works** with real sprints
|
||||||
|
3. **Begin PMO foundation** (Phase 9)
|
||||||
|
4. **Implement PMO commands** (Phase 10)
|
||||||
|
5. **Test with multiple projects** (Phase 11)
|
||||||
|
6. **Deploy to production** (Phase 12)
|
||||||
1010
docs/references/PLUGIN-PROJMAN.md
Normal file
1010
docs/references/PLUGIN-PROJMAN.md
Normal file
File diff suppressed because it is too large
Load Diff
639
docs/references/PROJECT-SUMMARY.md
Normal file
639
docs/references/PROJECT-SUMMARY.md
Normal file
@@ -0,0 +1,639 @@
|
|||||||
|
# Project Management Plugins - Project Summary
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This project builds two Claude Code plugins that transform a proven 15-sprint workflow into reusable, distributable tools for managing software development with Gitea, Wiki.js, and agile methodologies.
|
||||||
|
|
||||||
|
**Status:** Planning phase complete, ready for implementation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Two Plugins
|
||||||
|
|
||||||
|
### 1. projman (Single-Repository)
|
||||||
|
|
||||||
|
**Purpose:** Project management for individual repositories
|
||||||
|
**Users:** Developers, Team Leads
|
||||||
|
**Build Order:** Build FIRST
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Sprint planning with AI agents
|
||||||
|
- Issue creation with 43-label taxonomy
|
||||||
|
- Lessons learned capture in Wiki.js
|
||||||
|
- Branch-aware security model
|
||||||
|
- Hybrid configuration system
|
||||||
|
|
||||||
|
**Reference:** [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md)
|
||||||
|
|
||||||
|
### 2. projman-pmo (Multi-Project)
|
||||||
|
|
||||||
|
**Purpose:** PMO coordination across organization
|
||||||
|
**Users:** PMO Coordinators, Engineering Managers, CTOs
|
||||||
|
**Build Order:** Build SECOND (after projman validated)
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- Cross-project status aggregation
|
||||||
|
- Dependency tracking and visualization
|
||||||
|
- Resource conflict detection
|
||||||
|
- Release coordination
|
||||||
|
- Company-wide lessons learned search
|
||||||
|
|
||||||
|
**Reference:** [PLUGIN-PMO.md](./PLUGIN-PMO.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Architecture
|
||||||
|
|
||||||
|
### Shared MCP Servers
|
||||||
|
|
||||||
|
Both plugins share the same MCP server codebase at repository root (`mcp-servers/`):
|
||||||
|
|
||||||
|
**1. Gitea MCP Server**
|
||||||
|
- Issue management (CRUD operations)
|
||||||
|
- Label taxonomy system (43 labels)
|
||||||
|
- Mode detection (project vs company-wide)
|
||||||
|
|
||||||
|
**Reference:** [MCP-GITEA.md](./MCP-GITEA.md)
|
||||||
|
|
||||||
|
**2. Wiki.js MCP Server**
|
||||||
|
- Documentation management
|
||||||
|
- Lessons learned capture and search
|
||||||
|
- GraphQL API integration
|
||||||
|
- Company-wide knowledge base
|
||||||
|
|
||||||
|
**Reference:** [MCP-WIKIJS.md](./MCP-WIKIJS.md)
|
||||||
|
|
||||||
|
### Mode Detection
|
||||||
|
|
||||||
|
The MCP servers detect their operating mode based on environment variables:
|
||||||
|
|
||||||
|
**Project Mode (projman):**
|
||||||
|
- `GITEA_REPO` present → operates on single repository
|
||||||
|
- `WIKIJS_PROJECT` present → operates on single project path
|
||||||
|
|
||||||
|
**Company Mode (pmo):**
|
||||||
|
- No `GITEA_REPO` → operates on all repositories
|
||||||
|
- No `WIKIJS_PROJECT` → operates on entire company namespace
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
hyperhivelabs/claude-plugins/
|
||||||
|
├── mcp-servers/ # ← SHARED BY BOTH PLUGINS
|
||||||
|
│ ├── gitea/ # Gitea MCP Server
|
||||||
|
│ │ ├── .venv/
|
||||||
|
│ │ ├── requirements.txt
|
||||||
|
│ │ ├── mcp_server/
|
||||||
|
│ │ └── tests/
|
||||||
|
│ └── wikijs/ # Wiki.js MCP Server
|
||||||
|
│ ├── .venv/
|
||||||
|
│ ├── requirements.txt
|
||||||
|
│ ├── mcp_server/
|
||||||
|
│ └── tests/
|
||||||
|
├── projman/ # ← PROJECT PLUGIN
|
||||||
|
│ ├── .claude-plugin/
|
||||||
|
│ │ └── plugin.json
|
||||||
|
│ ├── .mcp.json # Points to ../mcp-servers/
|
||||||
|
│ ├── commands/
|
||||||
|
│ │ ├── sprint-plan.md
|
||||||
|
│ │ ├── sprint-start.md
|
||||||
|
│ │ ├── sprint-status.md
|
||||||
|
│ │ ├── sprint-close.md
|
||||||
|
│ │ └── labels-sync.md
|
||||||
|
│ ├── agents/
|
||||||
|
│ │ ├── planner.md
|
||||||
|
│ │ ├── orchestrator.md
|
||||||
|
│ │ └── executor.md
|
||||||
|
│ ├── skills/
|
||||||
|
│ │ └── label-taxonomy/
|
||||||
|
│ ├── README.md
|
||||||
|
│ └── CONFIGURATION.md
|
||||||
|
└── projman-pmo/ # ← PMO PLUGIN
|
||||||
|
├── .claude-plugin/
|
||||||
|
│ └── plugin.json
|
||||||
|
├── .mcp.json # Points to ../mcp-servers/
|
||||||
|
├── commands/
|
||||||
|
│ ├── pmo-status.md
|
||||||
|
│ ├── pmo-priorities.md
|
||||||
|
│ ├── pmo-dependencies.md
|
||||||
|
│ └── pmo-schedule.md
|
||||||
|
├── agents/
|
||||||
|
│ └── pmo-coordinator.md
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration Architecture
|
||||||
|
|
||||||
|
### Hybrid Configuration System
|
||||||
|
|
||||||
|
The plugins use a hybrid configuration approach that balances security and flexibility:
|
||||||
|
|
||||||
|
**System-Level (Once per machine):**
|
||||||
|
- `~/.config/claude/gitea.env` - Gitea credentials
|
||||||
|
- `~/.config/claude/wikijs.env` - Wiki.js credentials
|
||||||
|
|
||||||
|
**Project-Level (Per repository):**
|
||||||
|
- `project-root/.env` - Repository and project paths
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Single token per service (update once)
|
||||||
|
- Project isolation
|
||||||
|
- Security (tokens never committed)
|
||||||
|
- Easy multi-project setup
|
||||||
|
|
||||||
|
### Configuration Example
|
||||||
|
|
||||||
|
**System-Level:**
|
||||||
|
```bash
|
||||||
|
# ~/.config/claude/gitea.env
|
||||||
|
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
||||||
|
GITEA_API_TOKEN=your_token
|
||||||
|
GITEA_OWNER=hyperhivelabs
|
||||||
|
|
||||||
|
# ~/.config/claude/wikijs.env
|
||||||
|
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
|
||||||
|
WIKIJS_API_TOKEN=your_token
|
||||||
|
WIKIJS_BASE_PATH=/hyper-hive-labs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Project-Level:**
|
||||||
|
```bash
|
||||||
|
# project-root/.env (for projman)
|
||||||
|
GITEA_REPO=cuisineflow
|
||||||
|
WIKIJS_PROJECT=projects/cuisineflow
|
||||||
|
|
||||||
|
# No .env needed for pmo (company-wide mode)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Architectural Decisions
|
||||||
|
|
||||||
|
### 1. Two MCP Servers (Shared)
|
||||||
|
|
||||||
|
**Decision:** Separate Gitea and Wiki.js servers at repository root
|
||||||
|
**Why:**
|
||||||
|
- Clear separation of concerns
|
||||||
|
- Independent configuration
|
||||||
|
- Better maintainability
|
||||||
|
- Professional architecture
|
||||||
|
|
||||||
|
### 2. Python Implementation
|
||||||
|
|
||||||
|
**Decision:** Python 3.11+ for MCP servers
|
||||||
|
**Why:**
|
||||||
|
- Better suited for configuration management
|
||||||
|
- Modular code structure
|
||||||
|
- Easier to maintain and extend
|
||||||
|
- Good async support
|
||||||
|
|
||||||
|
### 3. Wiki.js for Lessons Learned
|
||||||
|
|
||||||
|
**Decision:** Use Wiki.js instead of Git-based Wiki
|
||||||
|
**Why:**
|
||||||
|
- Rich editor and search
|
||||||
|
- Built-in tag system
|
||||||
|
- Version history
|
||||||
|
- Web-based collaboration
|
||||||
|
- GraphQL API
|
||||||
|
- Company-wide accessibility
|
||||||
|
|
||||||
|
### 4. Hybrid Configuration
|
||||||
|
|
||||||
|
**Decision:** System-level + project-level configuration
|
||||||
|
**Why:**
|
||||||
|
- Single token per service (security)
|
||||||
|
- Per-project customization (flexibility)
|
||||||
|
- Easy multi-project setup
|
||||||
|
- Never commit tokens to git
|
||||||
|
|
||||||
|
### 5. Mode Detection in MCP Servers
|
||||||
|
|
||||||
|
**Decision:** Detect mode based on environment variables
|
||||||
|
**Why:**
|
||||||
|
- Same codebase for both plugins
|
||||||
|
- No code duplication
|
||||||
|
- Fix bugs once, both benefit
|
||||||
|
- Clear separation of concerns
|
||||||
|
|
||||||
|
### 6. Build Order: projman First
|
||||||
|
|
||||||
|
**Decision:** Build projman completely before starting pmo
|
||||||
|
**Why:**
|
||||||
|
- Validate core functionality
|
||||||
|
- Establish patterns
|
||||||
|
- Reduce risk
|
||||||
|
- PMO builds on projman foundation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Three-Agent Model
|
||||||
|
|
||||||
|
### Projman Agents
|
||||||
|
|
||||||
|
**Planner Agent:**
|
||||||
|
- Sprint planning and architecture analysis
|
||||||
|
- Asks clarifying questions
|
||||||
|
- Suggests appropriate labels
|
||||||
|
- Creates Gitea issues
|
||||||
|
- Searches relevant lessons learned
|
||||||
|
|
||||||
|
**Orchestrator Agent:**
|
||||||
|
- Sprint progress monitoring
|
||||||
|
- Task coordination
|
||||||
|
- Blocker identification
|
||||||
|
- Git operations
|
||||||
|
- Generates lean execution prompts
|
||||||
|
|
||||||
|
**Executor Agent:**
|
||||||
|
- Implementation guidance
|
||||||
|
- Code review suggestions
|
||||||
|
- Testing strategy
|
||||||
|
- Quality standards enforcement
|
||||||
|
- Documentation
|
||||||
|
|
||||||
|
### PMO Agent
|
||||||
|
|
||||||
|
**PMO Coordinator:**
|
||||||
|
- Strategic view across all projects
|
||||||
|
- Cross-project dependency tracking
|
||||||
|
- Resource conflict detection
|
||||||
|
- Release coordination
|
||||||
|
- Delegates to projman agents for details
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Wiki.js Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
Wiki.js: https://wiki.hyperhivelabs.com
|
||||||
|
└── /hyper-hive-labs/
|
||||||
|
├── projects/ # Project-specific
|
||||||
|
│ ├── cuisineflow/
|
||||||
|
│ │ ├── lessons-learned/
|
||||||
|
│ │ │ ├── sprints/
|
||||||
|
│ │ │ ├── patterns/
|
||||||
|
│ │ │ └── INDEX.md
|
||||||
|
│ │ └── documentation/
|
||||||
|
│ ├── cuisineflow-site/
|
||||||
|
│ ├── intuit-engine/
|
||||||
|
│ └── hhl-site/
|
||||||
|
├── company/ # Company-wide
|
||||||
|
│ ├── processes/
|
||||||
|
│ ├── standards/
|
||||||
|
│ └── tools/
|
||||||
|
└── shared/ # Cross-project
|
||||||
|
├── architecture-patterns/
|
||||||
|
├── best-practices/
|
||||||
|
└── tech-stack/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Reference:** [MCP-WIKIJS.md](./MCP-WIKIJS.md#wiki-js-structure)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Label Taxonomy System
|
||||||
|
|
||||||
|
### 43-Label System
|
||||||
|
|
||||||
|
**Organization Labels (27):**
|
||||||
|
- Agent/2
|
||||||
|
- Complexity/3
|
||||||
|
- Efforts/5
|
||||||
|
- Priority/4
|
||||||
|
- Risk/3
|
||||||
|
- Source/4
|
||||||
|
- Type/6 (includes Type/Refactor)
|
||||||
|
|
||||||
|
**Repository Labels (16):**
|
||||||
|
- Component/9
|
||||||
|
- Tech/7
|
||||||
|
|
||||||
|
### Type/Refactor Label
|
||||||
|
|
||||||
|
**New organization-level label** for architectural work:
|
||||||
|
- Service extraction
|
||||||
|
- Architecture modifications
|
||||||
|
- Code restructuring
|
||||||
|
- Technical debt reduction
|
||||||
|
|
||||||
|
**Reference:** [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md#label-taxonomy-system)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Order & Phases
|
||||||
|
|
||||||
|
### Build projman First (Phases 1-8)
|
||||||
|
|
||||||
|
**Phase 1:** Core Infrastructure (MCP servers)
|
||||||
|
**Phase 2:** Sprint Planning Commands
|
||||||
|
**Phase 3:** Agent System
|
||||||
|
**Phase 4:** Lessons Learned System
|
||||||
|
**Phase 5:** Testing & Validation
|
||||||
|
**Phase 6:** Documentation & Refinement
|
||||||
|
**Phase 7:** Marketplace Preparation
|
||||||
|
**Phase 8:** Production Hardening
|
||||||
|
|
||||||
|
**Reference:** [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md#implementation-phases)
|
||||||
|
|
||||||
|
### Build pmo Second (Phases 9-12)
|
||||||
|
|
||||||
|
**Phase 9:** PMO Plugin Foundation
|
||||||
|
**Phase 10:** PMO Commands & Workflows
|
||||||
|
**Phase 11:** PMO Testing & Integration
|
||||||
|
**Phase 12:** Production Deployment
|
||||||
|
|
||||||
|
**Reference:** [PLUGIN-PMO.md](./PLUGIN-PMO.md#implementation-phases)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start Guide
|
||||||
|
|
||||||
|
### 1. System Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create config directory
|
||||||
|
mkdir -p ~/.config/claude
|
||||||
|
|
||||||
|
# Gitea config
|
||||||
|
cat > ~/.config/claude/gitea.env << EOF
|
||||||
|
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
||||||
|
GITEA_API_TOKEN=your_gitea_token
|
||||||
|
GITEA_OWNER=hyperhivelabs
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Wiki.js config
|
||||||
|
cat > ~/.config/claude/wikijs.env << EOF
|
||||||
|
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
|
||||||
|
WIKIJS_API_TOKEN=your_wikijs_token
|
||||||
|
WIKIJS_BASE_PATH=/hyper-hive-labs
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Secure files
|
||||||
|
chmod 600 ~/.config/claude/*.env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Project Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In each project root (for projman)
|
||||||
|
cat > .env << EOF
|
||||||
|
GITEA_REPO=cuisineflow
|
||||||
|
WIKIJS_PROJECT=projects/cuisineflow
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Add to .gitignore
|
||||||
|
echo ".env" >> .gitignore
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. MCP Server Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Gitea MCP Server
|
||||||
|
cd mcp-servers/gitea
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Wiki.js MCP Server
|
||||||
|
cd mcp-servers/wikijs
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Validate Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test MCP servers
|
||||||
|
python -m mcp_server.server --test # In each MCP directory
|
||||||
|
|
||||||
|
# Test plugin loading
|
||||||
|
claude plugin test projman
|
||||||
|
claude plugin test projman-pmo
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Document Organization
|
||||||
|
|
||||||
|
This documentation is organized into 4 focused files plus this summary:
|
||||||
|
|
||||||
|
### 1. Gitea MCP Server Reference
|
||||||
|
|
||||||
|
**File:** [MCP-GITEA.md](./MCP-GITEA.md)
|
||||||
|
|
||||||
|
**Contains:**
|
||||||
|
- Configuration setup
|
||||||
|
- Python implementation
|
||||||
|
- API client code
|
||||||
|
- Issue and label tools
|
||||||
|
- Testing strategies
|
||||||
|
- Mode detection
|
||||||
|
- Performance optimization
|
||||||
|
|
||||||
|
**Use when:** Implementing or troubleshooting Gitea integration
|
||||||
|
|
||||||
|
### 2. Wiki.js MCP Server Reference
|
||||||
|
|
||||||
|
**File:** [MCP-WIKIJS.md](./MCP-WIKIJS.md)
|
||||||
|
|
||||||
|
**Contains:**
|
||||||
|
- Configuration setup
|
||||||
|
- GraphQL client implementation
|
||||||
|
- Wiki.js structure
|
||||||
|
- Lessons learned system
|
||||||
|
- Documentation tools
|
||||||
|
- Company-wide patterns
|
||||||
|
- PMO multi-project methods
|
||||||
|
|
||||||
|
**Use when:** Implementing or troubleshooting Wiki.js integration
|
||||||
|
|
||||||
|
### 3. Projman Plugin Reference
|
||||||
|
|
||||||
|
**File:** [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md)
|
||||||
|
|
||||||
|
**Contains:**
|
||||||
|
- Plugin structure
|
||||||
|
- Commands (sprint-plan, sprint-start, sprint-status, sprint-close, labels-sync)
|
||||||
|
- Three agents (planner, orchestrator, executor)
|
||||||
|
- Sprint workflow
|
||||||
|
- Label taxonomy
|
||||||
|
- Branch-aware security
|
||||||
|
- Implementation phases 1-8
|
||||||
|
|
||||||
|
**Use when:** Building or using the projman plugin
|
||||||
|
|
||||||
|
### 4. PMO Plugin Reference
|
||||||
|
|
||||||
|
**File:** [PLUGIN-PMO.md](./PLUGIN-PMO.md)
|
||||||
|
|
||||||
|
**Contains:**
|
||||||
|
- PMO plugin structure
|
||||||
|
- Multi-project commands
|
||||||
|
- PMO coordinator agent
|
||||||
|
- Cross-project coordination
|
||||||
|
- Dependency tracking
|
||||||
|
- Resource conflict detection
|
||||||
|
- Implementation phases 9-12
|
||||||
|
|
||||||
|
**Use when:** Building or using the projman-pmo plugin
|
||||||
|
|
||||||
|
### 5. This Summary
|
||||||
|
|
||||||
|
**File:** PROJECT-SUMMARY.md (this document)
|
||||||
|
|
||||||
|
**Contains:**
|
||||||
|
- Project overview
|
||||||
|
- Architecture decisions
|
||||||
|
- Configuration approach
|
||||||
|
- Quick start guide
|
||||||
|
- References to detailed docs
|
||||||
|
|
||||||
|
**Use when:** Getting started or need high-level overview
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Success Metrics
|
||||||
|
|
||||||
|
### Technical Metrics
|
||||||
|
|
||||||
|
- Sprint planning time reduced by 40%
|
||||||
|
- Manual steps eliminated: 10+ per sprint
|
||||||
|
- Lessons learned capture rate: 100% (vs 0% before)
|
||||||
|
- Label accuracy on issues: 90%+
|
||||||
|
- Configuration setup time: < 5 minutes
|
||||||
|
|
||||||
|
### User Metrics
|
||||||
|
|
||||||
|
- User satisfaction: Better than current manual workflow
|
||||||
|
- Learning curve: < 1 hour to basic proficiency
|
||||||
|
- Error rate: < 5% incorrect operations
|
||||||
|
- Adoption rate: 100% team adoption within 1 month
|
||||||
|
|
||||||
|
### PMO Metrics
|
||||||
|
|
||||||
|
- Cross-project visibility: 100% (vs fragmented before)
|
||||||
|
- Dependency detection: Automated (vs manual tracking)
|
||||||
|
- Resource conflict identification: Proactive (vs reactive)
|
||||||
|
- Release coordination: Streamlined (vs ad-hoc)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critical Lessons from 15 Sprints
|
||||||
|
|
||||||
|
### Why Lessons Learned Is Critical
|
||||||
|
|
||||||
|
After 15 sprints without systematic lesson capture, repeated mistakes occurred:
|
||||||
|
- Claude Code infinite loops on similar issues: 2-3 times
|
||||||
|
- Same architectural mistakes: Multiple occurrences
|
||||||
|
- Forgotten optimizations: Re-discovered each time
|
||||||
|
|
||||||
|
**Solution:** Mandatory lessons learned capture at sprint close, searchable at sprint start
|
||||||
|
|
||||||
|
### Branch Detection Must Be 100% Reliable
|
||||||
|
|
||||||
|
Production accidents are unacceptable. Branch-aware security prevents:
|
||||||
|
- Accidental code changes on production branch
|
||||||
|
- Sprint planning on wrong branch
|
||||||
|
- Deployment mistakes
|
||||||
|
|
||||||
|
**Implementation:** Two layers - CLAUDE.md (file-level) + Plugin agents (tool-level)
|
||||||
|
|
||||||
|
### Configuration Complexity Is a Blocker
|
||||||
|
|
||||||
|
Previous attempts failed due to:
|
||||||
|
- Complex per-project setup
|
||||||
|
- Token management overhead
|
||||||
|
- Multiple configuration files
|
||||||
|
|
||||||
|
**Solution:** Hybrid approach - system-level tokens + simple project-level paths
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
### Immediate Actions
|
||||||
|
|
||||||
|
1. **Set up system configuration** (Gitea + Wiki.js tokens)
|
||||||
|
2. **Create Wiki.js base structure** at `/hyper-hive-labs`
|
||||||
|
3. **Begin Phase 1.1a** - Gitea MCP Server implementation
|
||||||
|
4. **Begin Phase 1.1b** - Wiki.js MCP Server implementation
|
||||||
|
|
||||||
|
### Phase Execution
|
||||||
|
|
||||||
|
1. **Phases 1-4:** Build core projman functionality
|
||||||
|
2. **Phase 5:** Validate with real sprint (e.g., Intuit Engine extraction)
|
||||||
|
3. **Phases 6-8:** Polish, document, and harden projman
|
||||||
|
4. **Phases 9-12:** Build and validate pmo plugin
|
||||||
|
|
||||||
|
### Validation Points
|
||||||
|
|
||||||
|
- **After Phase 1:** MCP servers working and tested
|
||||||
|
- **After Phase 4:** Complete projman workflow end-to-end
|
||||||
|
- **After Phase 5:** Real sprint successfully managed
|
||||||
|
- **After Phase 8:** Production-ready projman
|
||||||
|
- **After Phase 11:** Multi-project coordination validated
|
||||||
|
- **After Phase 12:** Complete system operational
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Important Reminders
|
||||||
|
|
||||||
|
1. **Build projman FIRST** - Don't start pmo until projman is validated
|
||||||
|
2. **MCP servers are SHARED** - Located at `mcp-servers/`, not inside plugins
|
||||||
|
3. **Lessons learned is critical** - Prevents repeated mistakes
|
||||||
|
4. **Test with real work** - Validate with actual sprints, not just unit tests
|
||||||
|
5. **Security first** - Branch detection must be 100% reliable
|
||||||
|
6. **Keep it simple** - Avoid over-engineering, focus on proven workflow
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
### Documentation Structure
|
||||||
|
|
||||||
|
**Need details on:**
|
||||||
|
- Gitea integration → [MCP-GITEA.md](./MCP-GITEA.md)
|
||||||
|
- Wiki.js integration → [MCP-WIKIJS.md](./MCP-WIKIJS.md)
|
||||||
|
- Projman usage → [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md)
|
||||||
|
- PMO usage → [PLUGIN-PMO.md](./PLUGIN-PMO.md)
|
||||||
|
- Overview → This document
|
||||||
|
|
||||||
|
### Quick Reference
|
||||||
|
|
||||||
|
| Question | Reference |
|
||||||
|
|----------|-----------|
|
||||||
|
| How do I set up configuration? | This document, "Quick Start Guide" |
|
||||||
|
| What's the repository structure? | This document, "Repository Structure" |
|
||||||
|
| How do Gitea tools work? | [MCP-GITEA.md](./MCP-GITEA.md) |
|
||||||
|
| How do Wiki.js tools work? | [MCP-WIKIJS.md](./MCP-WIKIJS.md) |
|
||||||
|
| How do I use sprint commands? | [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md#commands) |
|
||||||
|
| How do agents work? | [PLUGIN-PROJMAN.md](./PLUGIN-PROJMAN.md#three-agent-model) |
|
||||||
|
| How do I coordinate multiple projects? | [PLUGIN-PMO.md](./PLUGIN-PMO.md) |
|
||||||
|
| What's the build order? | This document, "Build Order & Phases" |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Timeline
|
||||||
|
|
||||||
|
**Planning:** Complete ✅
|
||||||
|
**Phase 1-8 (projman):** 6-8 weeks estimated
|
||||||
|
**Phase 9-12 (pmo):** 2-4 weeks estimated
|
||||||
|
**Total:** 8-12 weeks from start to production
|
||||||
|
|
||||||
|
**Note:** No fixed deadlines - work at sustainable pace and validate thoroughly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## You're Ready!
|
||||||
|
|
||||||
|
You have everything you need to build the projman and projman-pmo plugins. All architectural decisions are finalized and documented.
|
||||||
|
|
||||||
|
**Start here:** [MCP-GITEA.md](./MCP-GITEA.md) - Set up Gitea MCP Server
|
||||||
|
|
||||||
|
Good luck with the build! 🚀
|
||||||
@@ -1,325 +0,0 @@
|
|||||||
# DEFINITIVE ARCHITECTURE - FINAL CORRECT VERSION
|
|
||||||
|
|
||||||
## ⚠️ THIS IS THE ONLY CORRECT STRUCTURE ⚠️
|
|
||||||
|
|
||||||
If you see ANY other structure in ANY other document, **THIS ONE IS CORRECT**.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Repository Structure (FINAL)
|
|
||||||
|
|
||||||
```
|
|
||||||
your-gitea/hyperhivelabs/claude-plugins/
|
|
||||||
├── .claude-plugin/
|
|
||||||
│ └── marketplace.json
|
|
||||||
├── mcp-servers/ # ← SHARED BY BOTH PLUGINS
|
|
||||||
│ ├── gitea/
|
|
||||||
│ │ ├── .venv/
|
|
||||||
│ │ ├── requirements.txt
|
|
||||||
│ │ ├── mcp_server/
|
|
||||||
│ │ │ ├── __init__.py
|
|
||||||
│ │ │ ├── server.py
|
|
||||||
│ │ │ ├── config.py
|
|
||||||
│ │ │ ├── gitea_client.py
|
|
||||||
│ │ │ └── tools/
|
|
||||||
│ │ │ ├── __init__.py
|
|
||||||
│ │ │ ├── issues.py
|
|
||||||
│ │ │ └── labels.py
|
|
||||||
│ │ └── tests/
|
|
||||||
│ │ ├── test_config.py
|
|
||||||
│ │ ├── test_gitea_client.py
|
|
||||||
│ │ └── test_tools.py
|
|
||||||
│ └── wikijs/
|
|
||||||
│ ├── .venv/
|
|
||||||
│ ├── requirements.txt
|
|
||||||
│ ├── mcp_server/
|
|
||||||
│ │ ├── __init__.py
|
|
||||||
│ │ ├── server.py
|
|
||||||
│ │ ├── config.py
|
|
||||||
│ │ ├── wikijs_client.py
|
|
||||||
│ │ └── tools/
|
|
||||||
│ │ ├── __init__.py
|
|
||||||
│ │ ├── pages.py
|
|
||||||
│ │ ├── lessons_learned.py
|
|
||||||
│ │ └── documentation.py
|
|
||||||
│ └── tests/
|
|
||||||
│ ├── test_config.py
|
|
||||||
│ ├── test_wikijs_client.py
|
|
||||||
│ └── test_tools.py
|
|
||||||
├── projman/ # ← PROJECT PLUGIN
|
|
||||||
│ ├── .claude-plugin/
|
|
||||||
│ │ └── plugin.json
|
|
||||||
│ ├── .mcp.json # Points to ../mcp-servers/
|
|
||||||
│ ├── commands/
|
|
||||||
│ │ ├── sprint-plan.md
|
|
||||||
│ │ ├── sprint-start.md
|
|
||||||
│ │ ├── sprint-status.md
|
|
||||||
│ │ ├── sprint-close.md
|
|
||||||
│ │ └── labels-sync.md
|
|
||||||
│ ├── agents/
|
|
||||||
│ │ ├── planner.md
|
|
||||||
│ │ ├── orchestrator.md
|
|
||||||
│ │ └── executor.md
|
|
||||||
│ ├── skills/
|
|
||||||
│ │ └── label-taxonomy/
|
|
||||||
│ │ └── labels-reference.md
|
|
||||||
│ ├── README.md
|
|
||||||
│ └── CONFIGURATION.md
|
|
||||||
└── projman-pmo/ # ← PMO PLUGIN
|
|
||||||
├── .claude-plugin/
|
|
||||||
│ └── plugin.json
|
|
||||||
├── .mcp.json # Points to ../mcp-servers/
|
|
||||||
├── commands/
|
|
||||||
│ ├── pmo-status.md
|
|
||||||
│ ├── pmo-priorities.md
|
|
||||||
│ ├── pmo-dependencies.md
|
|
||||||
│ └── pmo-schedule.md
|
|
||||||
├── agents/
|
|
||||||
│ └── pmo-coordinator.md
|
|
||||||
└── README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Points
|
|
||||||
|
|
||||||
### 1. MCP Servers Are SHARED
|
|
||||||
- Location: `mcp-servers/` at repository root
|
|
||||||
- NOT inside `projman/` or `projman-pmo/`
|
|
||||||
- Built ONCE, used by BOTH plugins
|
|
||||||
|
|
||||||
### 2. Plugins Reference MCP Servers
|
|
||||||
- Both plugins use `.mcp.json` to point to `../mcp-servers/`
|
|
||||||
- No MCP code inside plugin directories
|
|
||||||
- Only commands, agents, and skills in plugin directories
|
|
||||||
|
|
||||||
### 3. Mode Detection
|
|
||||||
- MCP servers detect mode based on environment variables
|
|
||||||
- Project mode: When `GITEA_REPO` and `WIKIJS_PROJECT` present
|
|
||||||
- Company mode: When those variables absent (PMO)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration Files
|
|
||||||
|
|
||||||
### projman/.mcp.json
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"gitea-projman": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"GITEA_API_URL": "${GITEA_API_URL}",
|
|
||||||
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
|
||||||
"GITEA_OWNER": "${GITEA_OWNER}",
|
|
||||||
"GITEA_REPO": "${GITEA_REPO}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wikijs-projman": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
|
||||||
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
|
||||||
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}",
|
|
||||||
"WIKIJS_PROJECT": "${WIKIJS_PROJECT}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### projman-pmo/.mcp.json
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"gitea-pmo": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"GITEA_API_URL": "${GITEA_API_URL}",
|
|
||||||
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
|
||||||
"GITEA_OWNER": "${GITEA_OWNER}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wikijs-pmo": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
|
||||||
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
|
||||||
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Critical:** Both plugins point to `../mcp-servers/` using relative paths.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Setup Instructions
|
|
||||||
|
|
||||||
### 1. System Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create config directory
|
|
||||||
mkdir -p ~/.config/claude
|
|
||||||
|
|
||||||
# Gitea config
|
|
||||||
cat > ~/.config/claude/gitea.env << EOF
|
|
||||||
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
|
||||||
GITEA_API_TOKEN=your_token
|
|
||||||
GITEA_OWNER=hyperhivelabs
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Wiki.js config
|
|
||||||
cat > ~/.config/claude/wikijs.env << EOF
|
|
||||||
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
|
|
||||||
WIKIJS_API_TOKEN=your_token
|
|
||||||
WIKIJS_BASE_PATH=/hyper-hive-labs
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Secure files
|
|
||||||
chmod 600 ~/.config/claude/*.env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Project Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In each project root
|
|
||||||
cat > .env << EOF
|
|
||||||
GITEA_REPO=cuisineflow
|
|
||||||
WIKIJS_PROJECT=projects/cuisineflow
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Add to .gitignore
|
|
||||||
echo ".env" >> .gitignore
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Install MCP Servers (ONE TIME)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Gitea MCP Server
|
|
||||||
cd /path/to/claude-plugins/mcp-servers/gitea
|
|
||||||
python -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Wiki.js MCP Server
|
|
||||||
cd /path/to/claude-plugins/mcp-servers/wikijs
|
|
||||||
python -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## What Makes This Work
|
|
||||||
|
|
||||||
### Mode Detection in config.py
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-servers/gitea/mcp_server/config.py
|
|
||||||
def load(self):
|
|
||||||
# ... load configs ...
|
|
||||||
|
|
||||||
self.repo = os.getenv('GITEA_REPO') # Optional
|
|
||||||
|
|
||||||
if self.repo:
|
|
||||||
self.mode = 'project'
|
|
||||||
logger.info(f"Running in project mode: {self.repo}")
|
|
||||||
else:
|
|
||||||
self.mode = 'company'
|
|
||||||
logger.info("Running in company-wide mode (PMO)")
|
|
||||||
|
|
||||||
return {
|
|
||||||
'api_url': self.api_url,
|
|
||||||
'api_token': self.api_token,
|
|
||||||
'owner': self.owner,
|
|
||||||
'repo': self.repo,
|
|
||||||
'mode': self.mode
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Same MCP Code, Different Behavior
|
|
||||||
|
|
||||||
The SAME MCP server code runs differently based on environment variables:
|
|
||||||
|
|
||||||
**When projman calls it:**
|
|
||||||
- Has `GITEA_REPO` → operates on single repository
|
|
||||||
- Has `WIKIJS_PROJECT` → operates on single project path
|
|
||||||
|
|
||||||
**When projman-pmo calls it:**
|
|
||||||
- No `GITEA_REPO` → operates on all repositories
|
|
||||||
- No `WIKIJS_PROJECT` → operates on entire company namespace
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Visual Path Flow
|
|
||||||
|
|
||||||
### projman Plugin Flow
|
|
||||||
```
|
|
||||||
projman/.mcp.json
|
|
||||||
↓ (cwd: ../mcp-servers/gitea)
|
|
||||||
mcp-servers/gitea/mcp_server/server.py
|
|
||||||
↓ (loads config)
|
|
||||||
mcp-servers/gitea/mcp_server/config.py
|
|
||||||
↓ (detects GITEA_REPO present)
|
|
||||||
→ PROJECT MODE
|
|
||||||
```
|
|
||||||
|
|
||||||
### projman-pmo Plugin Flow
|
|
||||||
```
|
|
||||||
projman-pmo/.mcp.json
|
|
||||||
↓ (cwd: ../mcp-servers/gitea)
|
|
||||||
mcp-servers/gitea/mcp_server/server.py
|
|
||||||
↓ (loads config)
|
|
||||||
mcp-servers/gitea/mcp_server/config.py
|
|
||||||
↓ (detects NO GITEA_REPO)
|
|
||||||
→ COMPANY MODE
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## File Paths Quick Reference
|
|
||||||
|
|
||||||
### Gitea MCP Server Files
|
|
||||||
- Config loader: `mcp-servers/gitea/mcp_server/config.py`
|
|
||||||
- API client: `mcp-servers/gitea/mcp_server/gitea_client.py`
|
|
||||||
- Server entry: `mcp-servers/gitea/mcp_server/server.py`
|
|
||||||
- Issue tools: `mcp-servers/gitea/mcp_server/tools/issues.py`
|
|
||||||
- Label tools: `mcp-servers/gitea/mcp_server/tools/labels.py`
|
|
||||||
|
|
||||||
### Wiki.js MCP Server Files
|
|
||||||
- Config loader: `mcp-servers/wikijs/mcp_server/config.py`
|
|
||||||
- API client: `mcp-servers/wikijs/mcp_server/wikijs_client.py`
|
|
||||||
- Server entry: `mcp-servers/wikijs/mcp_server/server.py`
|
|
||||||
- Page tools: `mcp-servers/wikijs/mcp_server/tools/pages.py`
|
|
||||||
- Lessons tools: `mcp-servers/wikijs/mcp_server/tools/lessons_learned.py`
|
|
||||||
|
|
||||||
### Plugin Files
|
|
||||||
- projman config: `projman/.mcp.json`
|
|
||||||
- projman-pmo config: `projman-pmo/.mcp.json`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## This Is The Truth
|
|
||||||
|
|
||||||
**If ANY other document shows MCP servers inside plugin directories, that document is WRONG.**
|
|
||||||
|
|
||||||
**THIS document shows the CORRECT, FINAL architecture.**
|
|
||||||
|
|
||||||
Use this as your reference. Period.
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
# ProjMan Implementation - Document Index
|
|
||||||
|
|
||||||
All documentation for building the projman and projman-pmo plugins.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ START HERE - CORRECT ARCHITECTURE
|
|
||||||
|
|
||||||
### [CORRECT-ARCHITECTURE.md](./CORRECT-ARCHITECTURE.md)
|
|
||||||
**⚠️ THIS IS THE DEFINITIVE REFERENCE ⚠️**
|
|
||||||
**Use when:** You need to verify the correct repository structure
|
|
||||||
**Contains:**
|
|
||||||
- THE ONLY CORRECT repository structure
|
|
||||||
- MCP servers are SHARED at root level (`mcp-servers/` directory)
|
|
||||||
- Configuration file examples
|
|
||||||
- Setup instructions
|
|
||||||
- Path references
|
|
||||||
- Mode detection implementation
|
|
||||||
|
|
||||||
**If any other document conflicts with this, THIS ONE IS CORRECT.**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 Core Implementation Documents
|
|
||||||
|
|
||||||
### [projman-implementation-plan-updated.md](./projman-implementation-plan-updated.md)
|
|
||||||
**Purpose:** Complete, detailed implementation plan
|
|
||||||
**Use when:** Actually building the plugins (your main reference)
|
|
||||||
**Contains:**
|
|
||||||
- 12 detailed implementation phases
|
|
||||||
- Configuration architecture
|
|
||||||
- Complete code examples
|
|
||||||
- Success criteria per phase
|
|
||||||
- Testing strategies
|
|
||||||
- No timelines - work at your pace
|
|
||||||
- **Length:** Comprehensive (2000+ lines)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐍 Python-Specific Guides
|
|
||||||
|
|
||||||
### [projman-python-quickstart.md](./projman-python-quickstart.md)
|
|
||||||
**Purpose:** Python-specific implementation guide
|
|
||||||
**Use when:** Setting up Python environment, writing code
|
|
||||||
**Contains:**
|
|
||||||
- Python project structure
|
|
||||||
- Virtual environment setup
|
|
||||||
- Requirements.txt examples
|
|
||||||
- Configuration loader code
|
|
||||||
- Modular code patterns
|
|
||||||
- Testing with pytest
|
|
||||||
- Debugging tips
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ Architecture Documentation
|
|
||||||
|
|
||||||
### [two-mcp-architecture-guide.md](./two-mcp-architecture-guide.md)
|
|
||||||
**Purpose:** Deep dive into two-MCP-server architecture
|
|
||||||
**Use when:** Understanding the MCP server design
|
|
||||||
**Contains:**
|
|
||||||
- Wiki.js structure at `/hyper-hive-labs`
|
|
||||||
- Complete Gitea MCP server code
|
|
||||||
- Complete Wiki.js MCP server code (GraphQL)
|
|
||||||
- Configuration examples
|
|
||||||
- Mode detection implementation
|
|
||||||
- Setup instructions
|
|
||||||
- Migration guidance
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 How to Use These Documents
|
|
||||||
|
|
||||||
### Phase 1: Planning & Setup
|
|
||||||
1. Read **CORRECT-ARCHITECTURE.md** to understand the definitive repository structure
|
|
||||||
2. Review **projman-implementation-plan-updated.md** Phase 1 for setup overview
|
|
||||||
3. Set up your Gitea and Wiki.js instances
|
|
||||||
4. Create system-level configuration files
|
|
||||||
|
|
||||||
### Phase 2: Starting Implementation
|
|
||||||
1. Open **projman-implementation-plan-updated.md** (your main reference for all 12 phases)
|
|
||||||
2. Start with Phase 1.1a (Gitea MCP Server)
|
|
||||||
3. Reference **projman-python-quickstart.md** for Python patterns and virtual environment setup
|
|
||||||
4. Reference **two-mcp-architecture-guide.md** for detailed MCP server code examples
|
|
||||||
|
|
||||||
### Phase 3: During Development
|
|
||||||
1. **Main reference:** projman-implementation-plan-updated.md (follow phase by phase)
|
|
||||||
2. **Structure reference:** CORRECT-ARCHITECTURE.md (when in doubt about paths)
|
|
||||||
3. **Code patterns:** projman-python-quickstart.md
|
|
||||||
4. **Architecture deep dive:** two-mcp-architecture-guide.md
|
|
||||||
|
|
||||||
### Phase 4: Troubleshooting
|
|
||||||
1. Check **CORRECT-ARCHITECTURE.md** for definitive path references
|
|
||||||
2. Review configuration examples in **two-mcp-architecture-guide.md**
|
|
||||||
3. Check Python-specific debugging in **projman-python-quickstart.md**
|
|
||||||
4. Verify setup instructions in **projman-implementation-plan-updated.md** Phase 1.3
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📖 Document Relationships
|
|
||||||
|
|
||||||
```
|
|
||||||
CORRECT-ARCHITECTURE.md (definitive structure)
|
|
||||||
↓ (referenced by)
|
|
||||||
├── projman-implementation-plan-updated.md (main implementation guide)
|
|
||||||
│ ↓ (uses Python patterns from)
|
|
||||||
│ ├── projman-python-quickstart.md
|
|
||||||
│ ↓ (references architecture from)
|
|
||||||
│ └── two-mcp-architecture-guide.md
|
|
||||||
└── DOCUMENT-INDEX.md (this file - navigation)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 Quick Reference by Topic
|
|
||||||
|
|
||||||
### Repository Structure
|
|
||||||
- **Definitive reference:** CORRECT-ARCHITECTURE.md (lines 9-80)
|
|
||||||
- **Key point:** MCP servers are SHARED at `mcp-servers/` directory (not inside plugins)
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
- **Setup instructions:** CORRECT-ARCHITECTURE.md (lines 172-229)
|
|
||||||
- **Implementation details:** projman-implementation-plan-updated.md (Phase 1.3)
|
|
||||||
- **Python code examples:** projman-python-quickstart.md (lines 140-214)
|
|
||||||
- **Config loader:** two-mcp-architecture-guide.md (lines 281-358)
|
|
||||||
|
|
||||||
### MCP Servers
|
|
||||||
- **Architecture overview:** CORRECT-ARCHITECTURE.md (Key Points section)
|
|
||||||
- **Gitea MCP:** projman-implementation-plan-updated.md (Phase 1.1a)
|
|
||||||
- **Wiki.js MCP:** projman-implementation-plan-updated.md (Phase 1.1b)
|
|
||||||
- **Complete implementation:** two-mcp-architecture-guide.md (lines 277-680)
|
|
||||||
|
|
||||||
### Wiki.js Structure
|
|
||||||
- **Full structure:** two-mcp-architecture-guide.md (lines 13-70)
|
|
||||||
- **Path resolution:** projman-implementation-plan-updated.md (lines 110-115)
|
|
||||||
- **Integration:** projman-implementation-plan-updated.md (Phase 4.1)
|
|
||||||
|
|
||||||
### Python Patterns
|
|
||||||
- **Setup & dependencies:** projman-python-quickstart.md (lines 15-111)
|
|
||||||
- **Modular code structure:** projman-python-quickstart.md (lines 511-575)
|
|
||||||
- **Virtual environment:** projman-python-quickstart.md (lines 579-616)
|
|
||||||
|
|
||||||
### Sprint Workflow
|
|
||||||
- **Commands:** projman-implementation-plan-updated.md (Phase 2)
|
|
||||||
- **Agents:** projman-implementation-plan-updated.md (Phase 3)
|
|
||||||
- **Lessons Learned:** projman-implementation-plan-updated.md (Phase 4)
|
|
||||||
|
|
||||||
### PMO Plugin
|
|
||||||
- **Requirements:** projman-implementation-plan-updated.md (Phase 9)
|
|
||||||
- **Implementation:** projman-implementation-plan-updated.md (Phase 10-11)
|
|
||||||
- **Multi-project methods:** two-mcp-architecture-guide.md (lines 639-679)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Suggested Reading Order
|
|
||||||
|
|
||||||
### First Time (Understanding the Project)
|
|
||||||
1. **CORRECT-ARCHITECTURE.md** (15 minutes)
|
|
||||||
- Understand the definitive repository structure
|
|
||||||
- See MCP server placement (shared at root)
|
|
||||||
- Review configuration approach
|
|
||||||
|
|
||||||
2. **projman-python-quickstart.md** (30 minutes)
|
|
||||||
- Understand Python setup
|
|
||||||
- See code patterns
|
|
||||||
- Virtual environment setup
|
|
||||||
|
|
||||||
3. **projman-implementation-plan-updated.md** (2-3 hours)
|
|
||||||
- Read Phase 1 in detail
|
|
||||||
- Skim Phases 2-12 to understand the flow
|
|
||||||
- This is your main implementation guide
|
|
||||||
|
|
||||||
4. **two-mcp-architecture-guide.md** (1 hour)
|
|
||||||
- Deep dive into MCP server architecture
|
|
||||||
- Complete code examples
|
|
||||||
- Wiki.js structure and integration
|
|
||||||
|
|
||||||
### During Implementation
|
|
||||||
- Keep **projman-implementation-plan-updated.md** open (your main reference)
|
|
||||||
- Reference **CORRECT-ARCHITECTURE.md** when unsure about paths
|
|
||||||
- Use **projman-python-quickstart.md** for Python-specific code
|
|
||||||
- Use **two-mcp-architecture-guide.md** for detailed MCP implementation
|
|
||||||
|
|
||||||
### When You Need Quick Answers
|
|
||||||
- **"What's the correct repository structure?"** → CORRECT-ARCHITECTURE.md
|
|
||||||
- **"How do I set up Python?"** → projman-python-quickstart.md
|
|
||||||
- **"How does configuration work?"** → CORRECT-ARCHITECTURE.md or two-mcp-architecture-guide.md
|
|
||||||
- **"What's the full MCP server code?"** → two-mcp-architecture-guide.md
|
|
||||||
- **"What do I build in Phase X?"** → projman-implementation-plan-updated.md
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Document Statistics
|
|
||||||
|
|
||||||
| Document | Lines | Focus | Primary Use |
|
|
||||||
|----------|-------|-------|-------------|
|
|
||||||
| CORRECT-ARCHITECTURE.md | 325 | Definitive Structure | Reference (paths, config) |
|
|
||||||
| projman-implementation-plan-updated.md | 2081 | Complete Implementation | Main guide (building) |
|
|
||||||
| projman-python-quickstart.md | 727 | Python Patterns | Code patterns & setup |
|
|
||||||
| two-mcp-architecture-guide.md | 941 | Architecture Deep Dive | MCP implementation |
|
|
||||||
|
|
||||||
**Total:** ~4,074 lines of comprehensive documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Pre-Implementation Checklist
|
|
||||||
|
|
||||||
Before starting Phase 1, verify you have:
|
|
||||||
- [ ] Read CORRECT-ARCHITECTURE.md (understand structure)
|
|
||||||
- [ ] Understand the two-MCP-server architecture (Gitea + Wiki.js)
|
|
||||||
- [ ] Understand shared MCP codebase at `mcp-servers/` (not in plugin dirs)
|
|
||||||
- [ ] Understand Wiki.js structure at `/hyper-hive-labs`
|
|
||||||
- [ ] Understand hybrid configuration (system + project levels)
|
|
||||||
- [ ] Python 3.11+ installed
|
|
||||||
- [ ] Access to Gitea instance
|
|
||||||
- [ ] Access to Wiki.js instance
|
|
||||||
- [ ] API tokens for both services
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Key Architectural Decisions
|
|
||||||
|
|
||||||
These are the final decisions documented across all files:
|
|
||||||
|
|
||||||
1. **Two MCP Servers** - Separate Gitea and Wiki.js servers for better maintainability
|
|
||||||
2. **Shared MCP Codebase** - Located at `mcp-servers/` (root level), used by both plugins
|
|
||||||
3. **Python Implementation** - MCP servers written in Python 3.11+
|
|
||||||
4. **Hybrid Configuration** - System-level tokens + project-level paths
|
|
||||||
5. **Wiki.js for Lessons** - Superior to Git-based Wiki for documentation and search
|
|
||||||
6. **Mode Detection** - MCP servers detect project vs company-wide mode via environment variables
|
|
||||||
7. **Build Order** - projman first (Phases 1-8), then projman-pmo (Phases 9-12)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 You're Ready!
|
|
||||||
|
|
||||||
You have everything you need to build the projman and projman-pmo plugins. All architectural decisions are finalized and documented.
|
|
||||||
|
|
||||||
**Start here:** [projman-implementation-plan-updated.md](./projman-implementation-plan-updated.md) - Phase 1.1a
|
|
||||||
|
|
||||||
Good luck with the build!
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,729 +0,0 @@
|
|||||||
# ProjMan Plugins - Python Quick Start
|
|
||||||
|
|
||||||
This guide provides Python-specific setup and development information for the projman and projman-pmo plugins.
|
|
||||||
|
|
||||||
> **⚠️ IMPORTANT:** For the definitive repository structure, refer to [CORRECT-ARCHITECTURE.md](./CORRECT-ARCHITECTURE.md). This guide shows Python-specific patterns and setup.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Technology Stack
|
|
||||||
|
|
||||||
- **MCP Server:** Python 3.11+
|
|
||||||
- **Commands:** Markdown files
|
|
||||||
- **Agents:** Markdown files
|
|
||||||
- **Dependencies:** pip with requirements.txt
|
|
||||||
- **Virtual Environment:** .venv (per plugin)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Initial Setup
|
|
||||||
|
|
||||||
### 1. System Requirements
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Python 3.11 or higher
|
|
||||||
python --version
|
|
||||||
|
|
||||||
# pip (latest)
|
|
||||||
pip --version
|
|
||||||
|
|
||||||
# git
|
|
||||||
git --version
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. System-Level Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create config directory
|
|
||||||
mkdir -p ~/.config/claude
|
|
||||||
|
|
||||||
# Create gitea.env with your credentials
|
|
||||||
cat > ~/.config/claude/gitea.env << EOF
|
|
||||||
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
|
||||||
GITEA_API_TOKEN=your_token_here
|
|
||||||
GITEA_OWNER=hyperhivelabs
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Secure the file
|
|
||||||
chmod 600 ~/.config/claude/gitea.env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Project-Level Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In each repository root
|
|
||||||
echo "GITEA_REPO=cuisineflow" > .env
|
|
||||||
|
|
||||||
# Add to .gitignore
|
|
||||||
echo ".env" >> .gitignore
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## MCP Server Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
hyperhivelabs/claude-plugins/
|
|
||||||
├── mcp-servers/ # SHARED by both plugins
|
|
||||||
│ ├── gitea/
|
|
||||||
│ │ ├── .venv/
|
|
||||||
│ │ ├── requirements.txt
|
|
||||||
│ │ ├── mcp_server/
|
|
||||||
│ │ │ ├── __init__.py
|
|
||||||
│ │ │ ├── server.py
|
|
||||||
│ │ │ ├── config.py
|
|
||||||
│ │ │ ├── gitea_client.py
|
|
||||||
│ │ │ └── tools/
|
|
||||||
│ │ └── tests/
|
|
||||||
│ └── wikijs/
|
|
||||||
│ ├── .venv/
|
|
||||||
│ ├── requirements.txt
|
|
||||||
│ ├── mcp_server/
|
|
||||||
│ │ ├── __init__.py
|
|
||||||
│ │ ├── server.py
|
|
||||||
│ │ ├── config.py
|
|
||||||
│ │ └── wikijs_client.py
|
|
||||||
│ └── tests/
|
|
||||||
├── projman/
|
|
||||||
│ ├── .mcp.json # Points to ../mcp-servers/
|
|
||||||
│ ├── commands/
|
|
||||||
│ └── agents/
|
|
||||||
└── projman-pmo/
|
|
||||||
├── .mcp.json # Points to ../mcp-servers/
|
|
||||||
└── commands/
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dependencies (requirements.txt)
|
|
||||||
|
|
||||||
```txt
|
|
||||||
# anthropic-sdk==0.18.0 # MCP SDK
|
|
||||||
anthropic-sdk>=0.18.0
|
|
||||||
# python-dotenv==1.0.0 # Environment variable loading
|
|
||||||
python-dotenv>=1.0.0
|
|
||||||
# requests==2.31.0 # HTTP client for Gitea API
|
|
||||||
requests>=2.31.0
|
|
||||||
# pydantic==2.5.0 # Data validation
|
|
||||||
pydantic>=2.5.0
|
|
||||||
# pytest==7.4.3 # Testing framework
|
|
||||||
pytest>=7.4.3
|
|
||||||
# pytest-asyncio==0.23.0 # Async testing support
|
|
||||||
pytest-asyncio>=0.23.0
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** Following your coding preferences, library versions are specified with comments showing the exact version being used.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Initial MCP Server Setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Navigate to MCP servers directory
|
|
||||||
cd /path/to/claude-plugins/mcp-servers/gitea
|
|
||||||
|
|
||||||
# Create virtual environment
|
|
||||||
python -m venv .venv
|
|
||||||
|
|
||||||
# Activate virtual environment
|
|
||||||
source .venv/bin/activate # Linux/Mac
|
|
||||||
# or
|
|
||||||
.venv\Scripts\activate # Windows
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Verify installation
|
|
||||||
python -c "import anthropic; print('SDK installed')"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Loader (config.py)
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-servers/gitea/mcp_server/config.py
|
|
||||||
from pathlib import Path
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
import os
|
|
||||||
from typing import Dict, Optional
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
"""Hybrid configuration loader for projman plugins"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.api_url: Optional[str] = None
|
|
||||||
self.api_token: Optional[str] = None
|
|
||||||
self.owner: Optional[str] = None
|
|
||||||
self.repo: Optional[str] = None
|
|
||||||
|
|
||||||
def load(self) -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
Load configuration from system and project levels.
|
|
||||||
Project-level configuration overrides system-level.
|
|
||||||
"""
|
|
||||||
# Load system config
|
|
||||||
system_config = Path.home() / '.config' / 'claude' / 'gitea.env'
|
|
||||||
if system_config.exists():
|
|
||||||
load_dotenv(system_config)
|
|
||||||
else:
|
|
||||||
raise FileNotFoundError(
|
|
||||||
f"System config not found: {system_config}\n"
|
|
||||||
"Create it with: mkdir -p ~/.config/claude && "
|
|
||||||
"cat > ~/.config/claude/gitea.env"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Load project config (overrides system)
|
|
||||||
project_config = Path.cwd() / '.env'
|
|
||||||
if project_config.exists():
|
|
||||||
load_dotenv(project_config, override=True)
|
|
||||||
|
|
||||||
# Extract values
|
|
||||||
self.api_url = os.getenv('GITEA_API_URL')
|
|
||||||
self.api_token = os.getenv('GITEA_API_TOKEN')
|
|
||||||
self.owner = os.getenv('GITEA_OWNER')
|
|
||||||
self.repo = os.getenv('GITEA_REPO') # Optional for PMO
|
|
||||||
|
|
||||||
# Validate required variables
|
|
||||||
self._validate()
|
|
||||||
|
|
||||||
return {
|
|
||||||
'api_url': self.api_url,
|
|
||||||
'api_token': self.api_token,
|
|
||||||
'owner': self.owner,
|
|
||||||
'repo': self.repo
|
|
||||||
}
|
|
||||||
|
|
||||||
def _validate(self) -> None:
|
|
||||||
"""Validate that required configuration is present"""
|
|
||||||
required = {
|
|
||||||
'GITEA_API_URL': self.api_url,
|
|
||||||
'GITEA_API_TOKEN': self.api_token,
|
|
||||||
'GITEA_OWNER': self.owner
|
|
||||||
}
|
|
||||||
|
|
||||||
missing = [key for key, value in required.items() if not value]
|
|
||||||
|
|
||||||
if missing:
|
|
||||||
raise ValueError(
|
|
||||||
f"Missing required configuration: {', '.join(missing)}\n"
|
|
||||||
"Check your ~/.config/claude/gitea.env file"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
config = Config()
|
|
||||||
config_dict = config.load()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Gitea API Client (gitea_client.py)
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-servers/gitea/mcp_server/gitea_client.py
|
|
||||||
import requests
|
|
||||||
from typing import List, Dict, Optional
|
|
||||||
from .config import Config
|
|
||||||
|
|
||||||
class GiteaClient:
|
|
||||||
"""Client for interacting with Gitea API"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
config = Config()
|
|
||||||
config_dict = config.load()
|
|
||||||
|
|
||||||
self.base_url = config_dict['api_url']
|
|
||||||
self.token = config_dict['api_token']
|
|
||||||
self.owner = config_dict['owner']
|
|
||||||
self.repo = config_dict.get('repo') # Optional
|
|
||||||
|
|
||||||
self.session = requests.Session()
|
|
||||||
self.session.headers.update({
|
|
||||||
'Authorization': f'token {self.token}',
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
})
|
|
||||||
|
|
||||||
def list_issues(
|
|
||||||
self,
|
|
||||||
state: str = 'open',
|
|
||||||
labels: Optional[List[str]] = None,
|
|
||||||
repo: Optional[str] = None
|
|
||||||
) -> List[Dict]:
|
|
||||||
"""
|
|
||||||
List issues from Gitea repository.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
state: Issue state (open, closed, all)
|
|
||||||
labels: Filter by labels
|
|
||||||
repo: Override configured repo (for PMO multi-repo)
|
|
||||||
"""
|
|
||||||
target_repo = repo or self.repo
|
|
||||||
if not target_repo:
|
|
||||||
raise ValueError("Repository not specified")
|
|
||||||
|
|
||||||
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues"
|
|
||||||
params = {'state': state}
|
|
||||||
|
|
||||||
if labels:
|
|
||||||
params['labels'] = ','.join(labels)
|
|
||||||
|
|
||||||
response = self.session.get(url, params=params)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def create_issue(
|
|
||||||
self,
|
|
||||||
title: str,
|
|
||||||
body: str,
|
|
||||||
labels: Optional[List[str]] = None,
|
|
||||||
repo: Optional[str] = None
|
|
||||||
) -> Dict:
|
|
||||||
"""Create a new issue in Gitea"""
|
|
||||||
target_repo = repo or self.repo
|
|
||||||
if not target_repo:
|
|
||||||
raise ValueError("Repository not specified")
|
|
||||||
|
|
||||||
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues"
|
|
||||||
data = {
|
|
||||||
'title': title,
|
|
||||||
'body': body
|
|
||||||
}
|
|
||||||
|
|
||||||
if labels:
|
|
||||||
data['labels'] = labels
|
|
||||||
|
|
||||||
response = self.session.post(url, json=data)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def get_labels(
|
|
||||||
self,
|
|
||||||
repo: Optional[str] = None
|
|
||||||
) -> List[Dict]:
|
|
||||||
"""Get all labels from repository"""
|
|
||||||
target_repo = repo or self.repo
|
|
||||||
if not target_repo:
|
|
||||||
raise ValueError("Repository not specified")
|
|
||||||
|
|
||||||
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/labels"
|
|
||||||
response = self.session.get(url)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
```
|
|
||||||
|
|
||||||
### MCP Server Entry Point (server.py)
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-servers/gitea/mcp_server/server.py
|
|
||||||
from anthropic import Anthropic
|
|
||||||
from .gitea_client import GiteaClient
|
|
||||||
from .tools import IssueTools, LabelTools, WikiTools
|
|
||||||
|
|
||||||
class ProjManMCPServer:
|
|
||||||
"""Main MCP server for projman plugin"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.gitea = GiteaClient()
|
|
||||||
self.issue_tools = IssueTools(self.gitea)
|
|
||||||
self.label_tools = LabelTools(self.gitea)
|
|
||||||
self.wiki_tools = WikiTools(self.gitea)
|
|
||||||
|
|
||||||
def register_tools(self):
|
|
||||||
"""Register all available MCP tools"""
|
|
||||||
return [
|
|
||||||
# Issue tools
|
|
||||||
self.issue_tools.list_issues,
|
|
||||||
self.issue_tools.get_issue,
|
|
||||||
self.issue_tools.create_issue,
|
|
||||||
self.issue_tools.update_issue,
|
|
||||||
self.issue_tools.add_comment,
|
|
||||||
|
|
||||||
# Label tools
|
|
||||||
self.label_tools.get_labels,
|
|
||||||
self.label_tools.suggest_labels,
|
|
||||||
|
|
||||||
# Wiki tools
|
|
||||||
self.wiki_tools.search_wiki,
|
|
||||||
self.wiki_tools.get_wiki_page,
|
|
||||||
self.wiki_tools.create_wiki_page
|
|
||||||
]
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
server = ProjManMCPServer()
|
|
||||||
# MCP server startup logic here
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Unit Tests
|
|
||||||
|
|
||||||
```python
|
|
||||||
# tests/test_config.py
|
|
||||||
import pytest
|
|
||||||
from pathlib import Path
|
|
||||||
from mcp_server.config import Config
|
|
||||||
|
|
||||||
def test_load_system_config(tmp_path):
|
|
||||||
"""Test loading system-level configuration"""
|
|
||||||
# Create mock system config
|
|
||||||
config_dir = tmp_path / '.config' / 'claude'
|
|
||||||
config_dir.mkdir(parents=True)
|
|
||||||
|
|
||||||
config_file = config_dir / 'gitea.env'
|
|
||||||
config_file.write_text(
|
|
||||||
"GITEA_API_URL=https://test.com/api/v1\n"
|
|
||||||
"GITEA_API_TOKEN=test_token\n"
|
|
||||||
"GITEA_OWNER=test_owner\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test config loading
|
|
||||||
config = Config()
|
|
||||||
# ... test assertions
|
|
||||||
|
|
||||||
def test_project_config_override(tmp_path):
|
|
||||||
"""Test that project config overrides system config"""
|
|
||||||
# ... test implementation
|
|
||||||
|
|
||||||
def test_missing_required_config():
|
|
||||||
"""Test error handling for missing configuration"""
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
config = Config()
|
|
||||||
config.load()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Integration Tests
|
|
||||||
|
|
||||||
```python
|
|
||||||
# tests/test_gitea_client.py
|
|
||||||
import pytest
|
|
||||||
from mcp_server.gitea_client import GiteaClient
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def gitea_client():
|
|
||||||
"""Fixture providing configured Gitea client"""
|
|
||||||
return GiteaClient()
|
|
||||||
|
|
||||||
def test_list_issues(gitea_client):
|
|
||||||
"""Test listing issues from Gitea"""
|
|
||||||
issues = gitea_client.list_issues(state='open')
|
|
||||||
assert isinstance(issues, list)
|
|
||||||
|
|
||||||
def test_create_issue(gitea_client):
|
|
||||||
"""Test creating an issue in Gitea"""
|
|
||||||
issue = gitea_client.create_issue(
|
|
||||||
title="Test Issue",
|
|
||||||
body="Test body",
|
|
||||||
labels=["Type/Bug"]
|
|
||||||
)
|
|
||||||
assert issue['title'] == "Test Issue"
|
|
||||||
assert "Type/Bug" in [label['name'] for label in issue['labels']]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Running Tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Activate virtual environment
|
|
||||||
source .venv/bin/activate
|
|
||||||
|
|
||||||
# Run all tests
|
|
||||||
pytest
|
|
||||||
|
|
||||||
# Run with coverage
|
|
||||||
pytest --cov=mcp_server --cov-report=html
|
|
||||||
|
|
||||||
# Run specific test file
|
|
||||||
pytest tests/test_config.py
|
|
||||||
|
|
||||||
# Run with verbose output
|
|
||||||
pytest -v
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## .mcp.json Configuration
|
|
||||||
|
|
||||||
### projman (Repository-Specific)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"gitea-projman": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"GITEA_API_URL": "${GITEA_API_URL}",
|
|
||||||
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
|
||||||
"GITEA_OWNER": "${GITEA_OWNER}",
|
|
||||||
"GITEA_REPO": "${GITEA_REPO}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wikijs-projman": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
|
||||||
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
|
||||||
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}",
|
|
||||||
"WIKIJS_PROJECT": "${WIKIJS_PROJECT}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### projman-pmo (Multi-Project)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"gitea-pmo": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"GITEA_API_URL": "${GITEA_API_URL}",
|
|
||||||
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
|
||||||
"GITEA_OWNER": "${GITEA_OWNER}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wikijs-pmo": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
|
||||||
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
|
||||||
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** Both plugins reference `../mcp-servers/` (shared location). PMO doesn't use `GITEA_REPO` since it operates across all repositories.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Modular Code Structure (Following Your Preferences)
|
|
||||||
|
|
||||||
### Single Responsibility Functions
|
|
||||||
|
|
||||||
```python
|
|
||||||
def validate_configuration(config: Dict[str, str]) -> None:
|
|
||||||
"""
|
|
||||||
Validate that all required configuration values are present.
|
|
||||||
Raises ValueError if any required values are missing.
|
|
||||||
"""
|
|
||||||
required_keys = ['api_url', 'api_token', 'owner']
|
|
||||||
missing = [key for key in required_keys if not config.get(key)]
|
|
||||||
|
|
||||||
if missing:
|
|
||||||
raise ValueError(f"Missing configuration: {', '.join(missing)}")
|
|
||||||
|
|
||||||
def load_system_config() -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
Load configuration from system-level gitea.env file.
|
|
||||||
Returns dictionary of configuration values.
|
|
||||||
"""
|
|
||||||
config_path = Path.home() / '.config' / 'claude' / 'gitea.env'
|
|
||||||
|
|
||||||
if not config_path.exists():
|
|
||||||
raise FileNotFoundError(f"System config not found: {config_path}")
|
|
||||||
|
|
||||||
load_dotenv(config_path)
|
|
||||||
|
|
||||||
return {
|
|
||||||
'api_url': os.getenv('GITEA_API_URL'),
|
|
||||||
'api_token': os.getenv('GITEA_API_TOKEN'),
|
|
||||||
'owner': os.getenv('GITEA_OWNER')
|
|
||||||
}
|
|
||||||
|
|
||||||
def load_project_config() -> Dict[str, Optional[str]]:
|
|
||||||
"""
|
|
||||||
Load project-specific configuration from local .env file.
|
|
||||||
Returns dictionary with 'repo' key, value may be None if not configured.
|
|
||||||
"""
|
|
||||||
project_env = Path.cwd() / '.env'
|
|
||||||
|
|
||||||
if project_env.exists():
|
|
||||||
load_dotenv(project_env, override=True)
|
|
||||||
|
|
||||||
return {
|
|
||||||
'repo': os.getenv('GITEA_REPO')
|
|
||||||
}
|
|
||||||
|
|
||||||
def merge_configurations(system: Dict, project: Dict) -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
Merge system and project configurations.
|
|
||||||
Project values override system values where present.
|
|
||||||
"""
|
|
||||||
merged = system.copy()
|
|
||||||
merged.update({k: v for k, v in project.items() if v is not None})
|
|
||||||
return merged
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main entry point that orchestrates configuration loading"""
|
|
||||||
system_config = load_system_config()
|
|
||||||
project_config = load_project_config()
|
|
||||||
final_config = merge_configurations(system_config, project_config)
|
|
||||||
validate_configuration(final_config)
|
|
||||||
return final_config
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Virtual Environment Management
|
|
||||||
|
|
||||||
### Creation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In plugin mcp-server directory
|
|
||||||
python -m venv .venv
|
|
||||||
```
|
|
||||||
|
|
||||||
### Activation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Linux/Mac
|
|
||||||
source .venv/bin/activate
|
|
||||||
|
|
||||||
# Windows
|
|
||||||
.venv\Scripts\activate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deactivation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
deactivate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cleanup & Rebuild
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Remove old virtual environment
|
|
||||||
rm -rf .venv
|
|
||||||
|
|
||||||
# Create fresh virtual environment
|
|
||||||
python -m venv .venv
|
|
||||||
|
|
||||||
# Activate and reinstall
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
### Enable Debug Logging
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Add to server.py
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logging.basicConfig(
|
|
||||||
level=logging.DEBUG,
|
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
**Issue:** Module not found
|
|
||||||
```bash
|
|
||||||
# Solution: Ensure PYTHONPATH is set in .mcp.json
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/mcp-server"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Issue:** Configuration not loading
|
|
||||||
```bash
|
|
||||||
# Solution: Check file permissions
|
|
||||||
chmod 600 ~/.config/claude/gitea.env
|
|
||||||
|
|
||||||
# Verify file exists
|
|
||||||
cat ~/.config/claude/gitea.env
|
|
||||||
```
|
|
||||||
|
|
||||||
**Issue:** API authentication failing
|
|
||||||
```bash
|
|
||||||
# Solution: Test token manually
|
|
||||||
curl -H "Authorization: token YOUR_TOKEN" \
|
|
||||||
https://your-gitea.com/api/v1/user
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Performance Optimization
|
|
||||||
|
|
||||||
### Caching with functools
|
|
||||||
|
|
||||||
```python
|
|
||||||
from functools import lru_cache
|
|
||||||
|
|
||||||
@lru_cache(maxsize=128)
|
|
||||||
def get_labels_cached(repo: str) -> List[Dict]:
|
|
||||||
"""Cached label retrieval to reduce API calls"""
|
|
||||||
return self.gitea.get_labels(repo)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Async Operations
|
|
||||||
|
|
||||||
```python
|
|
||||||
import asyncio
|
|
||||||
import aiohttp
|
|
||||||
|
|
||||||
async def fetch_multiple_repos(repos: List[str]) -> List[Dict]:
|
|
||||||
"""Fetch data from multiple repositories concurrently"""
|
|
||||||
async with aiohttp.ClientSession() as session:
|
|
||||||
tasks = [fetch_repo_data(session, repo) for repo in repos]
|
|
||||||
return await asyncio.gather(*tasks)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
1. **Set up system configuration** as shown above
|
|
||||||
2. **Create project configuration** in your first repository
|
|
||||||
3. **Navigate to Phase 1.1** of the implementation plan
|
|
||||||
4. **Build the MCP server** following the structure above
|
|
||||||
5. **Write tests** as you implement each component
|
|
||||||
6. **Test with real Gitea instance** early and often
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Differences from Node.js Approach
|
|
||||||
|
|
||||||
| Aspect | Node.js | Python (Your Choice) |
|
|
||||||
|--------|---------|---------------------|
|
|
||||||
| Dependencies | package.json | requirements.txt |
|
|
||||||
| Package Manager | npm/yarn | pip |
|
|
||||||
| Isolation | node_modules | .venv |
|
|
||||||
| Module System | ES6 imports | Python imports |
|
|
||||||
| Async | async/await | async/await |
|
|
||||||
| Type Checking | TypeScript | Type hints + Pydantic |
|
|
||||||
| Testing | Jest | pytest |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
|
|
||||||
- **Anthropic MCP SDK (Python):** https://github.com/anthropics/anthropic-sdk-python
|
|
||||||
- **Python Requests:** https://docs.python-requests.org/
|
|
||||||
- **Pydantic:** https://docs.pydantic.dev/
|
|
||||||
- **pytest:** https://docs.pytest.org/
|
|
||||||
- **Gitea API Docs:** https://docs.gitea.com/api/
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Ready to build! 🚀
|
|
||||||
@@ -1,944 +0,0 @@
|
|||||||
# Two MCP Server Architecture - Implementation Guide
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The projman plugin now uses **two separate MCP servers**:
|
|
||||||
1. **Gitea MCP Server** - Issues, labels, repository management
|
|
||||||
2. **Wiki.js MCP Server** - Documentation, lessons learned, knowledge base
|
|
||||||
|
|
||||||
This separation provides better maintainability, independent configuration, and leverages Wiki.js's superior documentation features.
|
|
||||||
|
|
||||||
> **⚠️ IMPORTANT:** For the definitive repository structure and configuration paths, refer to [CORRECT-ARCHITECTURE.md](./CORRECT-ARCHITECTURE.md). This guide provides detailed implementation examples and architectural deep-dive.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Wiki.js Structure at Hyper Hive Labs
|
|
||||||
|
|
||||||
### Company-Wide Organization
|
|
||||||
|
|
||||||
```
|
|
||||||
Wiki.js Instance: https://wiki.hyperhivelabs.com
|
|
||||||
└── /hyper-hive-labs/ # Base path for all HHL content
|
|
||||||
├── projects/ # Project-specific documentation
|
|
||||||
│ ├── cuisineflow/
|
|
||||||
│ │ ├── lessons-learned/
|
|
||||||
│ │ │ ├── sprints/
|
|
||||||
│ │ │ │ ├── sprint-01-auth.md
|
|
||||||
│ │ │ │ ├── sprint-02-api.md
|
|
||||||
│ │ │ │ └── ...
|
|
||||||
│ │ │ ├── patterns/
|
|
||||||
│ │ │ │ ├── service-extraction.md
|
|
||||||
│ │ │ │ └── database-migration.md
|
|
||||||
│ │ │ └── INDEX.md
|
|
||||||
│ │ └── documentation/
|
|
||||||
│ │ ├── architecture/
|
|
||||||
│ │ ├── api/
|
|
||||||
│ │ └── deployment/
|
|
||||||
│ ├── cuisineflow-site/
|
|
||||||
│ │ ├── lessons-learned/
|
|
||||||
│ │ └── documentation/
|
|
||||||
│ ├── intuit-engine/
|
|
||||||
│ │ ├── lessons-learned/
|
|
||||||
│ │ └── documentation/
|
|
||||||
│ └── hhl-site/
|
|
||||||
│ ├── lessons-learned/
|
|
||||||
│ └── documentation/
|
|
||||||
├── company/ # Company-wide documentation
|
|
||||||
│ ├── processes/
|
|
||||||
│ │ ├── onboarding.md
|
|
||||||
│ │ ├── deployment.md
|
|
||||||
│ │ └── code-review.md
|
|
||||||
│ ├── standards/
|
|
||||||
│ │ ├── python-style-guide.md
|
|
||||||
│ │ ├── api-design.md
|
|
||||||
│ │ └── security.md
|
|
||||||
│ └── tools/
|
|
||||||
│ ├── gitea-guide.md
|
|
||||||
│ ├── wikijs-guide.md
|
|
||||||
│ └── claude-plugins.md
|
|
||||||
└── shared/ # Cross-project resources
|
|
||||||
├── architecture-patterns/
|
|
||||||
│ ├── microservices.md
|
|
||||||
│ ├── api-gateway.md
|
|
||||||
│ └── database-per-service.md
|
|
||||||
├── best-practices/
|
|
||||||
│ ├── error-handling.md
|
|
||||||
│ ├── logging.md
|
|
||||||
│ └── testing.md
|
|
||||||
└── tech-stack/
|
|
||||||
├── python-ecosystem.md
|
|
||||||
├── docker.md
|
|
||||||
└── ci-cd.md
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration Architecture
|
|
||||||
|
|
||||||
### System-Level Configuration
|
|
||||||
|
|
||||||
**File: `~/.config/claude/gitea.env`**
|
|
||||||
```bash
|
|
||||||
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
|
||||||
GITEA_API_TOKEN=your_gitea_token_here
|
|
||||||
GITEA_OWNER=hyperhivelabs
|
|
||||||
```
|
|
||||||
|
|
||||||
**File: `~/.config/claude/wikijs.env`**
|
|
||||||
```bash
|
|
||||||
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
|
|
||||||
WIKIJS_API_TOKEN=your_wikijs_token_here
|
|
||||||
WIKIJS_BASE_PATH=/hyper-hive-labs
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why separate files?**
|
|
||||||
- Different services, different authentication
|
|
||||||
- Can update one without affecting the other
|
|
||||||
- Clear separation of concerns
|
|
||||||
- Easier to revoke/rotate tokens per service
|
|
||||||
|
|
||||||
### Project-Level Configuration
|
|
||||||
|
|
||||||
**File: `project-root/.env`**
|
|
||||||
```bash
|
|
||||||
# Gitea repository name
|
|
||||||
GITEA_REPO=cuisineflow
|
|
||||||
|
|
||||||
# Wiki.js project path (relative to /hyper-hive-labs)
|
|
||||||
WIKIJS_PROJECT=projects/cuisineflow
|
|
||||||
```
|
|
||||||
|
|
||||||
**Path Resolution:**
|
|
||||||
- Full Wiki.js path = `{WIKIJS_BASE_PATH}/{WIKIJS_PROJECT}`
|
|
||||||
- For cuisineflow: `/hyper-hive-labs/projects/cuisineflow`
|
|
||||||
- For intuit-engine: `/hyper-hive-labs/projects/intuit-engine`
|
|
||||||
|
|
||||||
### PMO Configuration (No Project Scope)
|
|
||||||
|
|
||||||
**PMO operates at company level:**
|
|
||||||
- **Gitea**: No `GITEA_REPO` → accesses all repos
|
|
||||||
- **Wiki.js**: No `WIKIJS_PROJECT` → accesses entire `/hyper-hive-labs` namespace
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Plugin Structure
|
|
||||||
|
|
||||||
### Repository Structure (CORRECT)
|
|
||||||
|
|
||||||
```
|
|
||||||
hyperhivelabs/claude-plugins/
|
|
||||||
├── mcp-servers/ # SHARED by both plugins
|
|
||||||
│ ├── gitea/
|
|
||||||
│ │ ├── .venv/
|
|
||||||
│ │ ├── requirements.txt
|
|
||||||
│ │ │ # anthropic-sdk>=0.18.0
|
|
||||||
│ │ │ # python-dotenv>=1.0.0
|
|
||||||
│ │ │ # requests>=2.31.0
|
|
||||||
│ │ │ # pydantic>=2.5.0
|
|
||||||
│ │ ├── .env.example
|
|
||||||
│ │ ├── mcp_server/
|
|
||||||
│ │ │ ├── __init__.py
|
|
||||||
│ │ │ ├── server.py
|
|
||||||
│ │ │ ├── config.py
|
|
||||||
│ │ │ ├── gitea_client.py
|
|
||||||
│ │ │ └── tools/
|
|
||||||
│ │ │ ├── issues.py
|
|
||||||
│ │ │ └── labels.py
|
|
||||||
│ │ └── tests/
|
|
||||||
│ │ ├── test_config.py
|
|
||||||
│ │ ├── test_gitea_client.py
|
|
||||||
│ │ └── test_tools.py
|
|
||||||
│ └── wikijs/
|
|
||||||
│ ├── .venv/
|
|
||||||
│ ├── requirements.txt
|
|
||||||
│ │ # anthropic-sdk>=0.18.0
|
|
||||||
│ │ # python-dotenv>=1.0.0
|
|
||||||
│ │ # gql>=3.4.0
|
|
||||||
│ │ # aiohttp>=3.9.0
|
|
||||||
│ │ # pydantic>=2.5.0
|
|
||||||
│ ├── .env.example
|
|
||||||
│ ├── mcp_server/
|
|
||||||
│ │ ├── __init__.py
|
|
||||||
│ │ ├── server.py
|
|
||||||
│ │ ├── config.py
|
|
||||||
│ │ ├── wikijs_client.py
|
|
||||||
│ │ └── tools/
|
|
||||||
│ │ ├── pages.py
|
|
||||||
│ │ ├── lessons_learned.py
|
|
||||||
│ │ └── documentation.py
|
|
||||||
│ └── tests/
|
|
||||||
│ ├── test_config.py
|
|
||||||
│ ├── test_wikijs_client.py
|
|
||||||
│ └── test_tools.py
|
|
||||||
├── projman/ # Project plugin
|
|
||||||
│ ├── .claude-plugin/
|
|
||||||
│ │ └── plugin.json
|
|
||||||
│ ├── .mcp.json # Points to ../mcp-servers/
|
|
||||||
│ ├── commands/
|
|
||||||
│ │ ├── sprint-plan.md
|
|
||||||
│ │ ├── sprint-start.md
|
|
||||||
│ │ ├── sprint-status.md
|
|
||||||
│ │ ├── sprint-close.md
|
|
||||||
│ │ └── labels-sync.md
|
|
||||||
│ ├── agents/
|
|
||||||
│ │ ├── planner.md
|
|
||||||
│ │ ├── orchestrator.md
|
|
||||||
│ │ └── executor.md
|
|
||||||
│ ├── skills/
|
|
||||||
│ │ └── label-taxonomy/
|
|
||||||
│ │ └── labels-reference.md
|
|
||||||
│ ├── README.md
|
|
||||||
│ └── CONFIGURATION.md
|
|
||||||
└── projman-pmo/ # PMO plugin
|
|
||||||
├── .claude-plugin/
|
|
||||||
│ └── plugin.json
|
|
||||||
├── .mcp.json # Points to ../mcp-servers/
|
|
||||||
├── commands/
|
|
||||||
│ ├── pmo-status.md
|
|
||||||
│ ├── pmo-priorities.md
|
|
||||||
│ ├── pmo-dependencies.md
|
|
||||||
│ └── pmo-schedule.md
|
|
||||||
├── agents/
|
|
||||||
│ └── pmo-coordinator.md
|
|
||||||
└── README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## MCP Configuration Files
|
|
||||||
|
|
||||||
### projman .mcp.json (Project-Scoped)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"gitea-projman": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"GITEA_API_URL": "${GITEA_API_URL}",
|
|
||||||
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
|
||||||
"GITEA_OWNER": "${GITEA_OWNER}",
|
|
||||||
"GITEA_REPO": "${GITEA_REPO}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wikijs-projman": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
|
||||||
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
|
||||||
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}",
|
|
||||||
"WIKIJS_PROJECT": "${WIKIJS_PROJECT}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### projman-pmo .mcp.json (Company-Wide)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"gitea-pmo": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
|
|
||||||
"GITEA_API_URL": "${GITEA_API_URL}",
|
|
||||||
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
|
|
||||||
"GITEA_OWNER": "${GITEA_OWNER}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wikijs-pmo": {
|
|
||||||
"command": "python",
|
|
||||||
"args": ["-m", "mcp_server.server"],
|
|
||||||
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"env": {
|
|
||||||
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
|
|
||||||
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
|
|
||||||
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
|
|
||||||
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Critical Notes:**
|
|
||||||
- Both plugins reference `../mcp-servers/` (shared location at repository root)
|
|
||||||
- **projman**: Includes `GITEA_REPO` and `WIKIJS_PROJECT` for project-scoped operations
|
|
||||||
- **projman-pmo**: Omits project-specific variables for company-wide operations
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Wiki.js MCP Server Implementation
|
|
||||||
|
|
||||||
### Configuration Loader
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-wikijs/mcp_server/config.py
|
|
||||||
from pathlib import Path
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
import os
|
|
||||||
from typing import Dict, Optional
|
|
||||||
|
|
||||||
class WikiJSConfig:
|
|
||||||
"""Hybrid configuration loader for Wiki.js"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.api_url: Optional[str] = None
|
|
||||||
self.api_token: Optional[str] = None
|
|
||||||
self.base_path: Optional[str] = None
|
|
||||||
self.project_path: Optional[str] = None
|
|
||||||
self.full_path: Optional[str] = None
|
|
||||||
|
|
||||||
def load(self) -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
Load Wiki.js configuration from system and project levels.
|
|
||||||
Composes full path from base_path + project_path.
|
|
||||||
"""
|
|
||||||
# Load system config
|
|
||||||
system_config = Path.home() / '.config' / 'claude' / 'wikijs.env'
|
|
||||||
if system_config.exists():
|
|
||||||
load_dotenv(system_config)
|
|
||||||
else:
|
|
||||||
raise FileNotFoundError(
|
|
||||||
f"System config not found: {system_config}\n"
|
|
||||||
"Create it with: cat > ~/.config/claude/wikijs.env"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Load project config (if exists, optional for PMO)
|
|
||||||
project_config = Path.cwd() / '.env'
|
|
||||||
if project_config.exists():
|
|
||||||
load_dotenv(project_config, override=True)
|
|
||||||
|
|
||||||
# Extract values
|
|
||||||
self.api_url = os.getenv('WIKIJS_API_URL')
|
|
||||||
self.api_token = os.getenv('WIKIJS_API_TOKEN')
|
|
||||||
self.base_path = os.getenv('WIKIJS_BASE_PATH') # /hyper-hive-labs
|
|
||||||
self.project_path = os.getenv('WIKIJS_PROJECT') # projects/cuisineflow (optional)
|
|
||||||
|
|
||||||
# Compose full path
|
|
||||||
if self.project_path:
|
|
||||||
self.full_path = f"{self.base_path}/{self.project_path}"
|
|
||||||
else:
|
|
||||||
# PMO mode - entire company namespace
|
|
||||||
self.full_path = self.base_path
|
|
||||||
|
|
||||||
# Validate required variables
|
|
||||||
self._validate()
|
|
||||||
|
|
||||||
return {
|
|
||||||
'api_url': self.api_url,
|
|
||||||
'api_token': self.api_token,
|
|
||||||
'base_path': self.base_path,
|
|
||||||
'project_path': self.project_path,
|
|
||||||
'full_path': self.full_path
|
|
||||||
}
|
|
||||||
|
|
||||||
def _validate(self) -> None:
|
|
||||||
"""Validate that required configuration is present"""
|
|
||||||
required = {
|
|
||||||
'WIKIJS_API_URL': self.api_url,
|
|
||||||
'WIKIJS_API_TOKEN': self.api_token,
|
|
||||||
'WIKIJS_BASE_PATH': self.base_path
|
|
||||||
}
|
|
||||||
|
|
||||||
missing = [key for key, value in required.items() if not value]
|
|
||||||
|
|
||||||
if missing:
|
|
||||||
raise ValueError(
|
|
||||||
f"Missing required configuration: {', '.join(missing)}\n"
|
|
||||||
"Check your ~/.config/claude/wikijs.env file"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### GraphQL Client
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-wikijs/mcp_server/wikijs_client.py
|
|
||||||
from gql import gql, Client
|
|
||||||
from gql.transport.aiohttp import AIOHTTPTransport
|
|
||||||
from typing import List, Dict, Optional
|
|
||||||
from .config import WikiJSConfig
|
|
||||||
|
|
||||||
class WikiJSClient:
|
|
||||||
"""Client for interacting with Wiki.js GraphQL API"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
config = WikiJSConfig()
|
|
||||||
config_dict = config.load()
|
|
||||||
|
|
||||||
self.api_url = config_dict['api_url']
|
|
||||||
self.api_token = config_dict['api_token']
|
|
||||||
self.base_path = config_dict['base_path']
|
|
||||||
self.project_path = config_dict.get('project_path')
|
|
||||||
self.full_path = config_dict['full_path']
|
|
||||||
|
|
||||||
# Set up GraphQL client
|
|
||||||
transport = AIOHTTPTransport(
|
|
||||||
url=self.api_url,
|
|
||||||
headers={'Authorization': f'Bearer {self.api_token}'}
|
|
||||||
)
|
|
||||||
self.client = Client(
|
|
||||||
transport=transport,
|
|
||||||
fetch_schema_from_transport=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def search_pages(
|
|
||||||
self,
|
|
||||||
query: str,
|
|
||||||
path: Optional[str] = None,
|
|
||||||
tags: Optional[List[str]] = None
|
|
||||||
) -> List[Dict]:
|
|
||||||
"""
|
|
||||||
Search pages in Wiki.js within a specific path.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
query: Search query string
|
|
||||||
path: Optional path to search within (defaults to full_path)
|
|
||||||
tags: Optional list of tags to filter by
|
|
||||||
"""
|
|
||||||
search_path = path or self.full_path
|
|
||||||
|
|
||||||
gql_query = gql("""
|
|
||||||
query SearchPages($query: String!, $path: String) {
|
|
||||||
pages {
|
|
||||||
search(query: $query, path: $path) {
|
|
||||||
results {
|
|
||||||
id
|
|
||||||
path
|
|
||||||
title
|
|
||||||
description
|
|
||||||
tags
|
|
||||||
updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
result = await self.client.execute(
|
|
||||||
gql_query,
|
|
||||||
variable_values={'query': query, 'path': search_path}
|
|
||||||
)
|
|
||||||
|
|
||||||
pages = result['pages']['search']['results']
|
|
||||||
|
|
||||||
# Filter by tags if specified
|
|
||||||
if tags:
|
|
||||||
pages = [
|
|
||||||
p for p in pages
|
|
||||||
if any(tag in p['tags'] for tag in tags)
|
|
||||||
]
|
|
||||||
|
|
||||||
return pages
|
|
||||||
|
|
||||||
async def get_page(self, path: str) -> Dict:
|
|
||||||
"""Fetch a specific page by path"""
|
|
||||||
gql_query = gql("""
|
|
||||||
query GetPage($path: String!) {
|
|
||||||
pages {
|
|
||||||
single(path: $path) {
|
|
||||||
id
|
|
||||||
path
|
|
||||||
title
|
|
||||||
description
|
|
||||||
content
|
|
||||||
tags
|
|
||||||
createdAt
|
|
||||||
updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
result = await self.client.execute(
|
|
||||||
gql_query,
|
|
||||||
variable_values={'path': path}
|
|
||||||
)
|
|
||||||
return result['pages']['single']
|
|
||||||
|
|
||||||
async def create_page(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
title: str,
|
|
||||||
content: str,
|
|
||||||
tags: List[str],
|
|
||||||
description: str = ""
|
|
||||||
) -> Dict:
|
|
||||||
"""
|
|
||||||
Create a new page in Wiki.js.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
path: Full path for the page (e.g., /hyper-hive-labs/projects/cuisineflow/lessons-learned/sprints/sprint-01)
|
|
||||||
title: Page title
|
|
||||||
content: Page content (markdown)
|
|
||||||
tags: List of tags
|
|
||||||
description: Optional description
|
|
||||||
"""
|
|
||||||
gql_mutation = gql("""
|
|
||||||
mutation CreatePage(
|
|
||||||
$path: String!,
|
|
||||||
$title: String!,
|
|
||||||
$content: String!,
|
|
||||||
$tags: [String]!,
|
|
||||||
$description: String
|
|
||||||
) {
|
|
||||||
pages {
|
|
||||||
create(
|
|
||||||
path: $path,
|
|
||||||
title: $title,
|
|
||||||
content: $content,
|
|
||||||
tags: $tags,
|
|
||||||
description: $description,
|
|
||||||
isPublished: true,
|
|
||||||
editor: "markdown"
|
|
||||||
) {
|
|
||||||
responseResult {
|
|
||||||
succeeded
|
|
||||||
errorCode
|
|
||||||
message
|
|
||||||
}
|
|
||||||
page {
|
|
||||||
id
|
|
||||||
path
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
result = await self.client.execute(
|
|
||||||
gql_mutation,
|
|
||||||
variable_values={
|
|
||||||
'path': path,
|
|
||||||
'title': title,
|
|
||||||
'content': content,
|
|
||||||
'tags': tags,
|
|
||||||
'description': description
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return result['pages']['create']
|
|
||||||
|
|
||||||
async def update_page(
|
|
||||||
self,
|
|
||||||
page_id: int,
|
|
||||||
content: str,
|
|
||||||
tags: Optional[List[str]] = None
|
|
||||||
) -> Dict:
|
|
||||||
"""Update existing page"""
|
|
||||||
variables = {
|
|
||||||
'id': page_id,
|
|
||||||
'content': content
|
|
||||||
}
|
|
||||||
|
|
||||||
if tags is not None:
|
|
||||||
variables['tags'] = tags
|
|
||||||
|
|
||||||
gql_mutation = gql("""
|
|
||||||
mutation UpdatePage(
|
|
||||||
$id: Int!,
|
|
||||||
$content: String!,
|
|
||||||
$tags: [String]
|
|
||||||
) {
|
|
||||||
pages {
|
|
||||||
update(
|
|
||||||
id: $id,
|
|
||||||
content: $content,
|
|
||||||
tags: $tags
|
|
||||||
) {
|
|
||||||
responseResult {
|
|
||||||
succeeded
|
|
||||||
errorCode
|
|
||||||
message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
result = await self.client.execute(gql_mutation, variable_values=variables)
|
|
||||||
return result['pages']['update']
|
|
||||||
|
|
||||||
async def list_pages(self, path: str) -> List[Dict]:
|
|
||||||
"""List all pages within a path"""
|
|
||||||
gql_query = gql("""
|
|
||||||
query ListPages($path: String!) {
|
|
||||||
pages {
|
|
||||||
list(path: $path, orderBy: TITLE) {
|
|
||||||
id
|
|
||||||
path
|
|
||||||
title
|
|
||||||
description
|
|
||||||
tags
|
|
||||||
updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
result = await self.client.execute(
|
|
||||||
gql_query,
|
|
||||||
variable_values={'path': path}
|
|
||||||
)
|
|
||||||
return result['pages']['list']
|
|
||||||
|
|
||||||
# Lessons Learned Specific Methods
|
|
||||||
|
|
||||||
async def create_lesson(
|
|
||||||
self,
|
|
||||||
sprint_name: str,
|
|
||||||
lesson_content: str,
|
|
||||||
tags: List[str]
|
|
||||||
) -> Dict:
|
|
||||||
"""
|
|
||||||
Create a lessons learned document for a sprint.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
sprint_name: Sprint identifier (e.g., "sprint-16-intuit-engine")
|
|
||||||
lesson_content: Full lesson markdown content
|
|
||||||
tags: Tags for categorization
|
|
||||||
"""
|
|
||||||
# Compose path within project's lessons-learned/sprints/
|
|
||||||
lesson_path = f"{self.full_path}/lessons-learned/sprints/{sprint_name}"
|
|
||||||
title = f"Sprint {sprint_name.split('-')[1]}: {' '.join(sprint_name.split('-')[2:]).title()}"
|
|
||||||
|
|
||||||
return await self.create_page(
|
|
||||||
path=lesson_path,
|
|
||||||
title=title,
|
|
||||||
content=lesson_content,
|
|
||||||
tags=tags,
|
|
||||||
description=f"Lessons learned from {sprint_name}"
|
|
||||||
)
|
|
||||||
|
|
||||||
async def search_lessons(
|
|
||||||
self,
|
|
||||||
query: str,
|
|
||||||
tags: Optional[List[str]] = None
|
|
||||||
) -> List[Dict]:
|
|
||||||
"""
|
|
||||||
Search lessons learned within the current project.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
query: Search keywords
|
|
||||||
tags: Optional tags to filter by
|
|
||||||
"""
|
|
||||||
lessons_path = f"{self.full_path}/lessons-learned"
|
|
||||||
return await self.search_pages(
|
|
||||||
query=query,
|
|
||||||
path=lessons_path,
|
|
||||||
tags=tags
|
|
||||||
)
|
|
||||||
|
|
||||||
# PMO Multi-Project Methods
|
|
||||||
|
|
||||||
async def search_all_projects(
|
|
||||||
self,
|
|
||||||
query: str,
|
|
||||||
tags: Optional[List[str]] = None
|
|
||||||
) -> Dict[str, List[Dict]]:
|
|
||||||
"""
|
|
||||||
Search lessons across all projects (PMO mode).
|
|
||||||
Returns results grouped by project.
|
|
||||||
"""
|
|
||||||
all_projects_path = f"{self.base_path}/projects"
|
|
||||||
results = await self.search_pages(
|
|
||||||
query=query,
|
|
||||||
path=all_projects_path,
|
|
||||||
tags=tags
|
|
||||||
)
|
|
||||||
|
|
||||||
# Group by project
|
|
||||||
by_project = {}
|
|
||||||
for result in results:
|
|
||||||
# Extract project name from path
|
|
||||||
# e.g., "/hyper-hive-labs/projects/cuisineflow/..." -> "cuisineflow"
|
|
||||||
path_parts = result['path'].split('/')
|
|
||||||
if len(path_parts) >= 4:
|
|
||||||
project = path_parts[3]
|
|
||||||
if project not in by_project:
|
|
||||||
by_project[project] = []
|
|
||||||
by_project[project].append(result)
|
|
||||||
|
|
||||||
return by_project
|
|
||||||
|
|
||||||
async def get_shared_docs(self, category: str) -> List[Dict]:
|
|
||||||
"""
|
|
||||||
Access company-wide shared documentation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
category: Category within shared/ (e.g., "architecture-patterns", "best-practices")
|
|
||||||
"""
|
|
||||||
shared_path = f"{self.base_path}/shared/{category}"
|
|
||||||
return await self.list_pages(path=shared_path)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## MCP Tools Structure
|
|
||||||
|
|
||||||
### Gitea MCP Tools
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-gitea/mcp_server/tools/issues.py
|
|
||||||
class IssueTools:
|
|
||||||
def __init__(self, gitea_client):
|
|
||||||
self.gitea = gitea_client
|
|
||||||
|
|
||||||
async def list_issues(self, state='open', labels=None):
|
|
||||||
"""List issues in current repository"""
|
|
||||||
return await self.gitea.list_issues(state=state, labels=labels)
|
|
||||||
|
|
||||||
async def get_issue(self, issue_number):
|
|
||||||
"""Get specific issue details"""
|
|
||||||
return await self.gitea.get_issue(issue_number)
|
|
||||||
|
|
||||||
async def create_issue(self, title, body, labels=None):
|
|
||||||
"""Create new issue"""
|
|
||||||
return await self.gitea.create_issue(title, body, labels)
|
|
||||||
|
|
||||||
# ... other issue tools
|
|
||||||
|
|
||||||
# mcp-gitea/mcp_server/tools/labels.py
|
|
||||||
class LabelTools:
|
|
||||||
def __init__(self, gitea_client):
|
|
||||||
self.gitea = gitea_client
|
|
||||||
|
|
||||||
async def get_labels(self):
|
|
||||||
"""Get all labels from repository"""
|
|
||||||
return await self.gitea.get_labels()
|
|
||||||
|
|
||||||
async def suggest_labels(self, context):
|
|
||||||
"""Suggest appropriate labels based on context"""
|
|
||||||
# Label suggestion logic using taxonomy
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
### Wiki.js MCP Tools
|
|
||||||
|
|
||||||
```python
|
|
||||||
# mcp-wikijs/mcp_server/tools/pages.py
|
|
||||||
class PageTools:
|
|
||||||
def __init__(self, wikijs_client):
|
|
||||||
self.wikijs = wikijs_client
|
|
||||||
|
|
||||||
async def search_pages(self, query, path=None, tags=None):
|
|
||||||
"""Search Wiki.js pages"""
|
|
||||||
return await self.wikijs.search_pages(query, path, tags)
|
|
||||||
|
|
||||||
async def get_page(self, path):
|
|
||||||
"""Get specific page"""
|
|
||||||
return await self.wikijs.get_page(path)
|
|
||||||
|
|
||||||
async def create_page(self, path, title, content, tags):
|
|
||||||
"""Create new page"""
|
|
||||||
return await self.wikijs.create_page(path, title, content, tags)
|
|
||||||
|
|
||||||
# ... other page tools
|
|
||||||
|
|
||||||
# mcp-wikijs/mcp_server/tools/lessons_learned.py
|
|
||||||
class LessonsLearnedTools:
|
|
||||||
def __init__(self, wikijs_client):
|
|
||||||
self.wikijs = wikijs_client
|
|
||||||
|
|
||||||
async def create_lesson(self, sprint_name, content, tags):
|
|
||||||
"""Create lessons learned document"""
|
|
||||||
return await self.wikijs.create_lesson(sprint_name, content, tags)
|
|
||||||
|
|
||||||
async def search_lessons(self, query, tags=None):
|
|
||||||
"""Search past lessons"""
|
|
||||||
return await self.wikijs.search_lessons(query, tags)
|
|
||||||
|
|
||||||
async def search_all_projects(self, query, tags=None):
|
|
||||||
"""Search lessons across all projects (PMO)"""
|
|
||||||
return await self.wikijs.search_all_projects(query, tags)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Setup Instructions
|
|
||||||
|
|
||||||
### 1. System Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create config directory
|
|
||||||
mkdir -p ~/.config/claude
|
|
||||||
|
|
||||||
# Create Gitea config
|
|
||||||
cat > ~/.config/claude/gitea.env << EOF
|
|
||||||
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
|
|
||||||
GITEA_API_TOKEN=your_gitea_token
|
|
||||||
GITEA_OWNER=hyperhivelabs
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Create Wiki.js config
|
|
||||||
cat > ~/.config/claude/wikijs.env << EOF
|
|
||||||
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
|
|
||||||
WIKIJS_API_TOKEN=your_wikijs_token
|
|
||||||
WIKIJS_BASE_PATH=/hyper-hive-labs
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Secure config files
|
|
||||||
chmod 600 ~/.config/claude/*.env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Project Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In each project root
|
|
||||||
cat > .env << EOF
|
|
||||||
GITEA_REPO=cuisineflow
|
|
||||||
WIKIJS_PROJECT=projects/cuisineflow
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Add to .gitignore
|
|
||||||
echo ".env" >> .gitignore
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Install MCP Servers
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Gitea MCP Server
|
|
||||||
cd /path/to/claude-plugins/mcp-servers/gitea
|
|
||||||
python -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Wiki.js MCP Server
|
|
||||||
cd /path/to/claude-plugins/mcp-servers/wikijs
|
|
||||||
python -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Initialize Wiki.js Structure
|
|
||||||
|
|
||||||
Create the base structure in Wiki.js web interface:
|
|
||||||
1. Navigate to https://wiki.hyperhivelabs.com
|
|
||||||
2. Create `/hyper-hive-labs` page
|
|
||||||
3. Create `/hyper-hive-labs/projects` page
|
|
||||||
4. Create `/hyper-hive-labs/company` page
|
|
||||||
5. Create `/hyper-hive-labs/shared` page
|
|
||||||
|
|
||||||
Or use the Wiki.js API:
|
|
||||||
```python
|
|
||||||
# One-time setup script
|
|
||||||
import asyncio
|
|
||||||
from wikijs_client import WikiJSClient
|
|
||||||
|
|
||||||
async def initialize_wiki_structure():
|
|
||||||
client = WikiJSClient()
|
|
||||||
|
|
||||||
# Create base pages
|
|
||||||
await client.create_page(
|
|
||||||
path="/hyper-hive-labs",
|
|
||||||
title="Hyper Hive Labs",
|
|
||||||
content="# Hyper Hive Labs Documentation",
|
|
||||||
tags=["company"]
|
|
||||||
)
|
|
||||||
|
|
||||||
await client.create_page(
|
|
||||||
path="/hyper-hive-labs/projects",
|
|
||||||
title="Projects",
|
|
||||||
content="# Project Documentation",
|
|
||||||
tags=["projects"]
|
|
||||||
)
|
|
||||||
|
|
||||||
# ... create other base pages
|
|
||||||
|
|
||||||
asyncio.run(initialize_wiki_structure())
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Benefits of This Architecture
|
|
||||||
|
|
||||||
### 1. Separation of Concerns
|
|
||||||
- **Gitea MCP**: Project tracking, issues, labels
|
|
||||||
- **Wiki.js MCP**: Knowledge management, documentation
|
|
||||||
|
|
||||||
### 2. Independent Configuration
|
|
||||||
- Update Gitea credentials without affecting Wiki.js
|
|
||||||
- Different token expiration policies
|
|
||||||
- Independent service availability
|
|
||||||
|
|
||||||
### 3. Better Documentation Features
|
|
||||||
- Wiki.js rich editor
|
|
||||||
- Built-in search and indexing
|
|
||||||
- Tag system
|
|
||||||
- Version history
|
|
||||||
- Access control
|
|
||||||
- Web-based review and editing
|
|
||||||
|
|
||||||
### 4. Company-Wide Knowledge Base
|
|
||||||
- Shared documentation accessible to all projects
|
|
||||||
- Cross-project lesson learning
|
|
||||||
- Best practices repository
|
|
||||||
- Onboarding materials
|
|
||||||
- Technical standards
|
|
||||||
|
|
||||||
### 5. Scalability
|
|
||||||
- Add new projects easily
|
|
||||||
- Grow company documentation organically
|
|
||||||
- PMO has visibility across everything
|
|
||||||
- Individual projects stay focused
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Migration from Single MCP
|
|
||||||
|
|
||||||
If you have existing Wiki content in Git:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Migration script
|
|
||||||
import asyncio
|
|
||||||
from wikijs_client import WikiJSClient
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
async def migrate_lessons_to_wikijs():
|
|
||||||
"""Migrate existing lessons learned from Git to Wiki.js"""
|
|
||||||
client = WikiJSClient()
|
|
||||||
|
|
||||||
# Read existing markdown files
|
|
||||||
lessons_dir = Path("wiki/lessons-learned/sprints")
|
|
||||||
|
|
||||||
for lesson_file in lessons_dir.glob("*.md"):
|
|
||||||
content = lesson_file.read_text()
|
|
||||||
sprint_name = lesson_file.stem
|
|
||||||
|
|
||||||
# Extract tags from content (e.g., from frontmatter or hashtags)
|
|
||||||
tags = extract_tags(content)
|
|
||||||
|
|
||||||
# Create in Wiki.js
|
|
||||||
await client.create_lesson(
|
|
||||||
sprint_name=sprint_name,
|
|
||||||
lesson_content=content,
|
|
||||||
tags=tags
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Migrated: {sprint_name}")
|
|
||||||
|
|
||||||
asyncio.run(migrate_lessons_to_wikijs())
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
1. **Set up Wiki.js instance** if not already done
|
|
||||||
2. **Create base structure** in Wiki.js
|
|
||||||
3. **Implement both MCP servers** (Phase 1.1a and 1.1b)
|
|
||||||
4. **Test configuration** with both services
|
|
||||||
5. **Migrate existing lessons** (if applicable)
|
|
||||||
6. **Start using with next sprint**
|
|
||||||
|
|
||||||
The two-MCP-server architecture provides a solid foundation for both project-level and company-wide knowledge management!
|
|
||||||
@@ -41,14 +41,16 @@
|
|||||||
},
|
},
|
||||||
"editor.folding": true,
|
"editor.folding": true,
|
||||||
"editor.foldingStrategy": "auto",
|
"editor.foldingStrategy": "auto",
|
||||||
|
// ===== Workbench Settings =====
|
||||||
"workbench.colorCustomizations": {
|
"workbench.colorCustomizations": {
|
||||||
"statusBar.background": "#d16003",
|
"statusBar.background": "#028bb4",
|
||||||
"statusBar.foreground": "#ffffff",
|
"statusBar.foreground": "#ffffff",
|
||||||
"statusBar.noFolderBackground": "#000000",
|
"statusBar.noFolderBackground": "#000000",
|
||||||
"statusBar.debuggingBackground": "#d16003",
|
"statusBar.debuggingBackground": "#028bb4",
|
||||||
"statusBar.border": "#d16003",
|
"statusBar.border": "#028bb4",
|
||||||
"statusBarItem.remoteBackground": "#aa4f04"
|
"statusBarItem.remoteBackground": "#036685"
|
||||||
},
|
},
|
||||||
|
"workbench.panel.defaultLocation": "right",
|
||||||
// ===== File Settings =====
|
// ===== File Settings =====
|
||||||
"files.trimTrailingWhitespace": true,
|
"files.trimTrailingWhitespace": true,
|
||||||
"files.insertFinalNewline": true,
|
"files.insertFinalNewline": true,
|
||||||
@@ -139,8 +141,8 @@
|
|||||||
"filePath": ".claude-plugins/marketplace.json",
|
"filePath": ".claude-plugins/marketplace.json",
|
||||||
"group": "Plugins"
|
"group": "Plugins"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"workbench.panel.defaultLocation": "right"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user