feat: Add OurDigital custom skills package (10 skills)

Complete implementation of OurDigital skills with dual-platform support
(Claude Desktop + Claude Code) following standardized structure.

Skills created:
- 01-ourdigital-brand-guide: Brand reference & style guidelines
- 02-ourdigital-blog: Korean blog drafts (blog.ourdigital.org)
- 03-ourdigital-journal: English essays (journal.ourdigital.org)
- 04-ourdigital-research: Research prompts & workflows
- 05-ourdigital-document: Notion-to-presentation pipeline
- 06-ourdigital-designer: Visual/image prompt generation
- 07-ourdigital-ad-manager: Ad copywriting & keyword research
- 08-ourdigital-trainer: Training materials & workshop planning
- 09-ourdigital-backoffice: Quotes, proposals, cost analysis
- 10-ourdigital-skill-creator: Meta skill for creating new skills

Features:
- YAML frontmatter with "ourdigital" or "our" prefix triggers
- Standardized directory structure (code/, desktop/, shared/, docs/)
- Shared environment setup (_ourdigital-shared/)
- Comprehensive reference documentation
- Cross-skill integration support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 16:50:17 +07:00
parent 7d20abe811
commit 0bc24d00b9
169 changed files with 9970 additions and 741 deletions

View File

@@ -0,0 +1,429 @@
---
name: multi-agent-guide
description: Use when user asks to "set up multi-agent collaboration", "initialize multi-agent project", "create agent guardrails", "set up team AI collaboration", "configure agent ownership rules", "create agent handoff protocols", mentions "multi-agent guide", "multi-agent setup", "agent coordination", "AI agent collaboration", or wants to configure a project for multiple AI agents (Claude, Gemini, Codex) working together with proper ownership rules, task management, and CI/CD integration.
version: 1.0.0
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion
---
# Multi-Agent Collaboration Guide Skill
This skill helps you set up a comprehensive multi-agent collaboration framework for complex software projects where multiple AI agents (Claude Code, Gemini, Codex, and Human) work together.
## Overview
The multi-agent setup creates:
| Component | Purpose |
|-----------|---------|
| **Agent Hierarchy** | Defines lead agent and sub-agents with clear authority levels |
| **Ownership Matrix** | Specifies which agent owns which files/directories |
| **Guardrails System** | Prevents conflicts through locks and task claiming |
| **Handoff Protocols** | Standardizes communication between agents |
| **CI/CD Integration** | Automated ownership verification in pipelines |
| **Pre-commit Hooks** | Local verification before commits |
## When to Use This Skill
Activate when users:
1. **Starting a complex project** requiring multiple AI agents
2. **Organizing existing project** for multi-agent collaboration
3. **Setting up guardrails** to prevent agent conflicts
4. **Implementing ownership rules** for files and directories
5. **Creating handoff protocols** between AI agents
6. **Configuring CI/CD** for multi-agent workflows
## Setup Workflow
### Phase 1: Assessment
Before setup, gather the following information:
```
1. Project type (Python, Node.js, monorepo, etc.)
2. Agent hierarchy (which agents will participate)
3. Primary ownership domains for each agent
4. Shared file coordination needs
5. CI/CD platform (GitHub Actions, GitLab CI, etc.)
```
### Phase 2: File Structure Creation
Create the following directory structure:
```
project-root/
├── .agent-state/ # Agent coordination state
│ ├── tasks.yaml # Task registry
│ └── locks.yaml # File lock registry
├── tools/ # Ownership verification scripts
│ └── check-ownership.py # Multi-agent ownership checker
├── AGENTS.md # Shared collaboration rules
├── GUARDRAILS.md # Ownership and enforcement rules
├── CLAUDE.md # Lead agent (Claude) directive
├── GEMINI.md # Sub-agent (Gemini) directive (optional)
├── CODEX.md # Sub-agent (Codex) directive (optional)
└── .pre-commit-config.yaml # Pre-commit hooks (update existing)
```
### Phase 3: Configuration
The setup configures:
1. **Agent identity** via `SEO_AGENT_AUTHOR` environment variable
2. **Ownership matrix** in check-ownership.py
3. **Task and lock state** in .agent-state/ YAML files
4. **Commit message format** enforcement: `[Agent] type(scope): description`
5. **Pre-commit hooks** for local verification
6. **CI/CD workflows** for PR verification (optional)
---
## File Templates
### AGENTS.md Template
The shared rules file should include:
```markdown
# AGENTS.md - Common Ground Rules & Collaboration Protocols
## Agent Hierarchy
| Agent | Role | Authority | Context File |
|-------|------|-----------|--------------|
| **Claude Code** | Lead / Orchestrator | Architecture, core logic, final decisions | `CLAUDE.md` |
| **Gemini** | Sub-agent | Google APIs, documentation, research | `GEMINI.md` |
| **Codex** | Sub-agent | Tests, boilerplate, docstrings | `CODEX.md` |
## Handoff Protocols
### Claude → Gemini Handoff
- Google API implementation
- Documentation writing
- Research tasks
### Claude → Codex Handoff
- Unit test generation
- Boilerplate models
- Docstring generation
## Commit Convention
[Agent] type(scope): description
Types: feat, fix, docs, test, refactor, chore
Agent tags: [Claude], [Gemini], [Codex], [Human]
```
### GUARDRAILS.md Template
The enforcement rules file should include:
```markdown
# GUARDRAILS.md - Ownership & Enforcement Rules
## Ownership Matrix
### Claude Primary Ownership
- `src/*/cli.py`
- `src/*/core/`
- Architecture-related files
### Gemini Primary Ownership
- `src/*/integrations/google/`
- `docs/`
- Research documentation
### Codex Primary Ownership
- `tests/`
- `src/*/models.py`
- `src/*/utils/`
### Shared Files (Claude Approves)
- `pyproject.toml`
- `config/*.yaml`
- `.github/workflows/`
### Unrestricted Files
- `.agent-state/`
- `.gitignore`
- `README.md`
## Lock System
Lock types:
- **exclusive**: Only one agent can modify
- **shared**: Multiple agents can read, one can write
- **override**: Claude override for conflict resolution
Lock file format (.agent-state/locks.yaml):
```yaml
version: "1.0"
locks:
- path: "src/module/"
agent: "claude"
lock_type: "exclusive"
task_id: "TASK-001"
expires_at: "2025-01-30T12:00:00Z"
```
## Task Claiming Protocol
1. Check task status in .agent-state/tasks.yaml
2. Claim task by setting agent and status
3. Acquire necessary file locks
4. Complete work
5. Release locks and mark task complete
```
### check-ownership.py Template
The ownership verification script should:
1. Define `OWNERSHIP_MATRIX` with regex patterns
2. Define `SHARED_FILES` requiring Claude approval
3. Define `UNRESTRICTED_FILES` anyone can modify
4. Check file ownership before allowing modifications
5. Verify lock status in `.agent-state/locks.yaml`
6. Validate commit message format
Key functions:
- `get_file_owner(filepath)` → Returns (owner, ownership_type)
- `is_file_locked(filepath, root)` → Returns (is_locked, lock_info)
- `verify_ownership(files, agent, root)` → Returns (violations, warnings)
- `check_commit_message(msg_file)` → Returns bool
---
## Setup Commands
### Quick Setup (Recommended)
When user requests multi-agent setup, follow these steps:
1. **Ask configuration questions**:
```
- What is your project name and type?
- Which agents will participate? (Claude, Gemini, Codex, custom)
- What are the main directories/domains for each agent?
- Do you want CI/CD integration? (GitHub Actions, GitLab CI)
```
2. **Create directory structure**:
```bash
mkdir -p .agent-state
mkdir -p tools
```
3. **Generate configuration files** from templates:
- AGENTS.md (customize based on project)
- GUARDRAILS.md (customize ownership matrix)
- Agent-specific .md files (CLAUDE.md, etc.)
- .agent-state/tasks.yaml (initialize empty)
- .agent-state/locks.yaml (initialize empty)
- tools/check-ownership.py (customize OWNERSHIP_MATRIX)
4. **Update pre-commit configuration**:
- Add check-ownership hook
- Add commit-message hook
5. **Optional: Create CI workflow**:
- GitHub Actions ownership-check.yml
- Or equivalent for other CI systems
### Environment Setup
Instruct users to set agent identity:
```bash
# Add to shell profile (.bashrc, .zshrc)
export SEO_AGENT_AUTHOR=claude # or gemini, codex, human
# Or use direnv (.envrc)
export SEO_AGENT_AUTHOR=claude
```
---
## Customization Guide
### Adding New Agents
1. Create `AGENTNAME.md` at project root
2. Add to AGENTS.md hierarchy table
3. Update OWNERSHIP_MATRIX in check-ownership.py
4. Add to VALID_AGENTS set
### Modifying Ownership Rules
1. Edit OWNERSHIP_MATRIX in check-ownership.py
2. Update GUARDRAILS.md documentation
3. Communicate changes to all agents
### Adjusting Lock Timeouts
Default lock expiration: 4 hours
To change, modify the task/lock creation logic to use different `expires_at` values.
---
## Integration with CI/CD
### GitHub Actions
Create `.github/workflows/ownership-check.yml`:
```yaml
name: Ownership Check
on:
pull_request:
branches: [main, develop]
jobs:
check-ownership:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install dependencies
run: pip install pyyaml
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
- name: Check ownership
env:
SEO_AGENT_AUTHOR: ci
run: |
python tools/check-ownership.py ${{ steps.changed-files.outputs.all_changed_files }}
```
### Pre-commit Integration
Add to `.pre-commit-config.yaml`:
```yaml
repos:
- repo: local
hooks:
- id: check-ownership
name: Check Agent Ownership
entry: python tools/check-ownership.py
language: python
always_run: true
pass_filenames: true
additional_dependencies: [pyyaml]
- id: check-commit-message
name: Check Commit Message Format
entry: python tools/check-ownership.py --check-commit-msg
language: python
stages: [commit-msg]
additional_dependencies: [pyyaml]
```
---
## Best Practices
### Agent Coordination
| Practice | Description |
|----------|-------------|
| **Claim before work** | Always claim tasks in .agent-state/tasks.yaml |
| **Lock during edits** | Acquire locks for files you're modifying |
| **Release promptly** | Don't hold locks longer than necessary |
| **Use handoff format** | Follow standard handoff protocol for delegation |
| **Attribution** | Always include agent tag in commit messages |
### Conflict Resolution
1. **Check locks first** - Don't modify locked files
2. **Escalate to Claude** - Claude can override locks
3. **Document conflicts** - Update GUARDRAILS.md if patterns emerge
4. **Communicate changes** - Notify other agents of ownership changes
### Code Style
Maintain consistent code style across agents:
| Aspect | Standard |
|--------|----------|
| Formatter | Black (Python), Prettier (JS) |
| Line length | 100 characters |
| Docstrings | Google-style |
| Type hints | Required |
---
## Reference Files
Supporting files in this skill:
| File | Purpose |
|------|---------|
| `templates/agents-md.md` | AGENTS.md template |
| `templates/guardrails-md.md` | GUARDRAILS.md template |
| `templates/claude-md.md` | CLAUDE.md template |
| `templates/gemini-md.md` | GEMINI.md template |
| `templates/codex-md.md` | CODEX.md template |
| `templates/tasks-yaml.yaml` | Tasks file template |
| `templates/locks-yaml.yaml` | Locks file template |
| `scripts/check-ownership.py` | Ownership verification script |
| `references/ownership-matrix.md` | Detailed ownership patterns |
| `examples/minimal-setup/` | Minimal 2-agent setup example |
| `examples/full-setup/` | Full 3-agent setup example |
---
## Commands
Available actions when this skill is active:
| Command | Description |
|---------|-------------|
| "Set up multi-agent collaboration" | Initialize full framework |
| "Add new agent [name]" | Add a new agent to existing setup |
| "Update ownership matrix" | Modify file ownership rules |
| "Check agent setup" | Verify configuration is correct |
| "Create handoff for [agent]" | Generate handoff document |
| "Initialize task" | Create new task in tasks.yaml |
---
## Troubleshooting
### Common Issues
**"Ownership violation" error**:
- Check `SEO_AGENT_AUTHOR` environment variable is set
- Verify file is in your agent's ownership domain
- Ask lead agent (Claude) for override if needed
**"File locked" error**:
- Check `.agent-state/locks.yaml` for active locks
- Wait for lock to expire or ask owner to release
- Claude can override locks if urgent
**Pre-commit hook fails**:
- Verify PyYAML is installed: `pip install pyyaml`
- Check `.agent-state/` directory exists
- Ensure commit message follows format
**CI workflow fails**:
- Verify changed files list is correct
- Check that check-ownership.py is in tools/
- Ensure Python and dependencies are available
---
*This skill is designed for complex projects requiring coordinated multi-agent collaboration with clear ownership, accountability, and conflict prevention.*

View File

@@ -0,0 +1,67 @@
# Minimal Multi-Agent Setup Example
This example shows the minimum files needed for a 2-agent setup (Claude + Codex).
## Directory Structure
```
project/
├── .agent-state/
│ ├── tasks.yaml
│ └── locks.yaml
├── tools/
│ └── check-ownership.py
├── AGENTS.md
├── GUARDRAILS.md
└── CLAUDE.md
```
## Files Created
1. **AGENTS.md** - Basic agent hierarchy (Claude lead, Codex sub-agent)
2. **GUARDRAILS.md** - Simplified ownership matrix
3. **CLAUDE.md** - Lead agent directive
4. **.agent-state/** - Task and lock management
5. **tools/check-ownership.py** - Verification script
## Setup Steps
1. Create directories:
```bash
mkdir -p .agent-state tools
```
2. Copy templates (customize as needed):
```bash
# From skill templates
cp templates/agents-md.md AGENTS.md
cp templates/guardrails-md.md GUARDRAILS.md
cp templates/claude-md.md CLAUDE.md
cp templates/tasks-yaml.yaml .agent-state/tasks.yaml
cp templates/locks-yaml.yaml .agent-state/locks.yaml
cp scripts/check-ownership.py tools/check-ownership.py
```
3. Set environment variable:
```bash
export SEO_AGENT_AUTHOR=claude
```
4. Verify setup:
```bash
python tools/check-ownership.py --verify-setup
```
## Ownership Matrix (Minimal)
| Agent | Owns |
|-------|------|
| Claude | `src/`, `CLAUDE.md`, `AGENTS.md`, `GUARDRAILS.md` |
| Codex | `tests/`, `CODEX.md` |
## Commit Format
```
[Claude] type(scope): description
[Codex] type(scope): description
```

View File

@@ -0,0 +1,233 @@
# Ownership Matrix Reference
This document provides detailed patterns for configuring the ownership matrix in `check-ownership.py`.
## Pattern Syntax
The ownership matrix uses Python regular expressions (regex) to match file paths.
### Common Patterns
| Pattern | Matches | Example Files |
|---------|---------|---------------|
| `^src/cli\.py$` | Exact file | `src/cli.py` |
| `^src/.*/cli\.py$` | Any subdirectory | `src/app/cli.py`, `src/core/cli.py` |
| `^src/core/` | Directory prefix | `src/core/main.py`, `src/core/utils/helper.py` |
| `^tests/` | All tests | `tests/test_main.py`, `tests/unit/test_foo.py` |
| `^docs/.*\.md$` | Markdown in docs | `docs/api.md`, `docs/guides/setup.md` |
| `\.py$` | All Python files | Any `.py` file |
### Regex Cheat Sheet
| Symbol | Meaning | Example |
|--------|---------|---------|
| `^` | Start of string | `^src/` matches paths starting with `src/` |
| `$` | End of string | `\.py$` matches paths ending with `.py` |
| `.` | Any character | `a.c` matches `abc`, `a1c`, etc. |
| `\.` | Literal dot | `\.py` matches `.py` |
| `*` | Zero or more | `a*` matches ``, `a`, `aa`, `aaa` |
| `+` | One or more | `a+` matches `a`, `aa`, `aaa` |
| `.*` | Any characters | `src/.*` matches anything starting with `src/` |
| `[abc]` | Character class | `[abc]` matches `a`, `b`, or `c` |
| `\w` | Word character | `\w+` matches words |
| `\d` | Digit | `\d+` matches numbers |
| `(a\|b)` | Alternation | `(foo\|bar)` matches `foo` or `bar` |
## Project-Specific Examples
### Python Project
```python
OWNERSHIP_MATRIX: Dict[str, str] = {
# Claude - Core application
r"^src/app/": "claude",
r"^src/core/": "claude",
r"^src/.*/cli\.py$": "claude",
r"^CLAUDE\.md$": "claude",
r"^AGENTS\.md$": "claude",
r"^GUARDRAILS\.md$": "claude",
# Gemini - APIs and documentation
r"^src/.*/api/": "gemini",
r"^src/.*/integrations/": "gemini",
r"^docs/": "gemini",
r"^GEMINI\.md$": "gemini",
# Codex - Testing and utilities
r"^tests/": "codex",
r"^src/.*/models\.py$": "codex",
r"^src/.*/utils/": "codex",
r"^CODEX\.md$": "codex",
}
```
### TypeScript Project
```python
OWNERSHIP_MATRIX: Dict[str, str] = {
# Claude - Core application
r"^src/app/": "claude",
r"^src/core/": "claude",
r"^src/index\.ts$": "claude",
r"^CLAUDE\.md$": "claude",
# Gemini - APIs and documentation
r"^src/api/": "gemini",
r"^src/services/": "gemini",
r"^docs/": "gemini",
r"^GEMINI\.md$": "gemini",
# Codex - Testing and utilities
r"^tests/": "codex",
r"^__tests__/": "codex",
r"^src/.*/.*\.test\.ts$": "codex",
r"^src/types/": "codex",
r"^src/utils/": "codex",
r"^CODEX\.md$": "codex",
}
```
### Monorepo Project
```python
OWNERSHIP_MATRIX: Dict[str, str] = {
# Claude - Core packages
r"^packages/core/": "claude",
r"^packages/cli/": "claude",
r"^CLAUDE\.md$": "claude",
# Gemini - API packages
r"^packages/api/": "gemini",
r"^packages/sdk/": "gemini",
r"^docs/": "gemini",
r"^GEMINI\.md$": "gemini",
# Codex - Testing and shared
r"^packages/testing/": "codex",
r"^packages/shared/": "codex",
r"^packages/.*/tests/": "codex",
r"^CODEX\.md$": "codex",
}
```
## Shared Files Configuration
Files that require coordination between agents:
```python
SHARED_FILES: Set[str] = {
# Package configuration
r"^pyproject\.toml$",
r"^package\.json$",
r"^Cargo\.toml$",
# Build configuration
r"^Makefile$",
r"^Dockerfile$",
r"^docker-compose\.ya?ml$",
# CI/CD
r"^\.github/workflows/",
r"^\.gitlab-ci\.yml$",
r"^\.circleci/",
# Project planning
r"^PROJECT_PLAN\.md$",
r"^ROADMAP\.md$",
r"^CHANGELOG\.md$",
}
```
## Unrestricted Files Configuration
Files any agent can modify:
```python
UNRESTRICTED_FILES: Set[str] = {
# Agent state
r"^\.agent-state/",
# Git configuration
r"^\.gitignore$",
r"^\.gitattributes$",
# Editor configuration
r"^\.vscode/",
r"^\.idea/",
# Documentation
r"^README\.md$",
r"^CONTRIBUTING\.md$",
r"^LICENSE$",
# Pre-commit
r"^\.pre-commit-config\.yaml$",
}
```
## Custom Agent Example
Adding a custom agent (e.g., "designer"):
```python
# 1. Add to valid agents
VALID_AGENTS = {"claude", "gemini", "codex", "human", "designer"}
# 2. Add ownership patterns
OWNERSHIP_MATRIX: Dict[str, str] = {
# ... existing patterns ...
# Designer - UI and styles
r"^src/components/": "designer",
r"^src/styles/": "designer",
r"^src/.*/.*\.css$": "designer",
r"^src/.*/.*\.scss$": "designer",
r"^DESIGNER\.md$": "designer",
}
# 3. Update commit message pattern in check_commit_message()
pattern = r"^\[(Claude|Gemini|Codex|Human|Designer|CI)\]\s+\w+(\([^)]+\))?:\s+.+"
```
## Testing Patterns
Test your patterns using Python:
```python
import re
def test_pattern(pattern: str, test_paths: list) -> None:
"""Test a regex pattern against multiple paths."""
for path in test_paths:
match = re.match(pattern, path)
print(f"{path}: {'MATCH' if match else 'NO MATCH'}")
# Example
test_pattern(r"^src/.*/cli\.py$", [
"src/cli.py", # NO MATCH (no subdirectory)
"src/app/cli.py", # MATCH
"src/core/cli.py", # MATCH
"src/a/b/cli.py", # MATCH
])
```
## Debugging Tips
1. **Pattern not matching?**
- Check for literal dots (use `\.` not `.`)
- Verify start `^` and end `$` anchors
- Test with simple paths first
2. **Pattern too broad?**
- Add more specific path components
- Use `$` to anchor end of pattern
- Add file extension matching
3. **Multiple agents matching?**
- First match wins
- Order patterns from specific to general
- Use more specific patterns for exceptions
---
*Customize the ownership matrix for your specific project structure.*

View File

@@ -0,0 +1,496 @@
#!/usr/bin/env python3
"""
Multi-Agent Ownership Verification Script
This script enforces file ownership rules and lock verification for the
multi-agent workflow defined in GUARDRAILS.md.
Usage:
# Verify files before commit
python tools/check-ownership.py path/to/file.py
# Check commit message format
python tools/check-ownership.py --check-commit-msg
# Verify setup
python tools/check-ownership.py --verify-setup
# List expired locks/tasks
python tools/check-ownership.py --list-expired
# Validate state files
python tools/check-ownership.py --validate-state
Environment:
SEO_AGENT_AUTHOR: Agent identity (claude|gemini|codex|human)
"""
import argparse
import os
import re
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Dict, List, Optional, Set, Tuple
try:
import yaml
except ImportError:
print("Warning: PyYAML not installed. Install with: pip install pyyaml")
yaml = None
# =============================================================================
# CUSTOMIZE: Ownership Matrix
# =============================================================================
# Modify these patterns to match your project structure
# Primary ownership rules: pattern -> owner
OWNERSHIP_MATRIX: Dict[str, str] = {
# Claude ownership (customize for your project)
r"^src/.*/cli\.py$": "claude",
r"^src/.*/core/": "claude",
r"^src/.*/main\.py$": "claude",
r"^CLAUDE\.md$": "claude",
r"^AGENTS\.md$": "claude",
r"^GUARDRAILS\.md$": "claude",
# Gemini ownership
r"^src/.*/integrations/google/": "gemini",
r"^src/.*/integrations/gsc\.py$": "gemini",
r"^src/.*/integrations/ga.*\.py$": "gemini",
r"^docs/.*\.md$": "gemini",
r"^GEMINI\.md$": "gemini",
# Codex ownership
r"^src/.*/models\.py$": "codex",
r"^src/.*/utils/": "codex",
r"^tests/": "codex",
r"^CODEX\.md$": "codex",
}
# Shared files (require coordination, Claude approves)
SHARED_FILES: Set[str] = {
r"^pyproject\.toml$",
r"^package\.json$",
r"^config/.*\.yaml$",
r"^config/.*\.json$",
r"^\\.github/workflows/",
r"^PROJECT_PLAN\.md$",
}
# Files that any agent can modify without ownership check
UNRESTRICTED_FILES: Set[str] = {
r"^\\.agent-state/",
r"^\\.pre-commit-config\\.yaml$",
r"^\\.gitignore$",
r"^README\\.md$",
}
# Valid agents (add custom agents here)
VALID_AGENTS = {"claude", "gemini", "codex", "human"}
# =============================================================================
# Helper Functions
# =============================================================================
def get_project_root() -> Path:
"""Find the project root directory."""
current = Path(__file__).resolve().parent
while current != current.parent:
if (current / "pyproject.toml").exists():
return current
if (current / "package.json").exists():
return current
if (current / ".git").exists():
return current
current = current.parent
return Path.cwd()
def get_agent_author() -> Optional[str]:
"""Get the current agent from environment variable."""
agent = os.environ.get("SEO_AGENT_AUTHOR", "").lower()
return agent if agent in VALID_AGENTS else None
def load_yaml_file(filepath: Path) -> Optional[dict]:
"""Load a YAML file safely."""
if yaml is None:
return None
if not filepath.exists():
return None
try:
with open(filepath, "r") as f:
return yaml.safe_load(f)
except Exception as e:
print(f"Warning: Could not load {filepath}: {e}")
return None
def get_file_owner(filepath: str) -> Tuple[Optional[str], str]:
"""
Determine the owner of a file.
Returns:
Tuple of (owner, ownership_type) where ownership_type is
'primary', 'shared', 'unrestricted', or 'unknown'
"""
# Normalize path
filepath = filepath.replace("\\", "/").lstrip("./")
# Check unrestricted first
for pattern in UNRESTRICTED_FILES:
if re.match(pattern, filepath):
return None, "unrestricted"
# Check shared files
for pattern in SHARED_FILES:
if re.match(pattern, filepath):
return "shared", "shared"
# Check primary ownership
for pattern, owner in OWNERSHIP_MATRIX.items():
if re.match(pattern, filepath):
return owner, "primary"
return None, "unknown"
def is_file_locked(filepath: str, root: Path) -> Tuple[bool, Optional[dict]]:
"""
Check if a file is locked by another agent.
Returns:
Tuple of (is_locked, lock_info)
"""
locks_file = root / ".agent-state" / "locks.yaml"
locks_data = load_yaml_file(locks_file)
if not locks_data or "locks" not in locks_data:
return False, None
filepath = filepath.replace("\\", "/").lstrip("./")
current_time = datetime.now(timezone.utc)
for lock in locks_data.get("locks", []):
if not lock:
continue
lock_path = lock.get("path", "").replace("\\", "/").lstrip("./")
# Check if path matches (exact or prefix for directories)
if filepath == lock_path or filepath.startswith(lock_path + "/"):
# Check if lock is expired
expires_at = lock.get("expires_at")
if expires_at:
try:
expiry = datetime.fromisoformat(expires_at.replace("Z", "+00:00"))
if current_time > expiry:
continue # Lock expired
except ValueError:
pass
return True, lock
return False, None
def check_commit_message(msg_file: str) -> bool:
"""
Verify commit message follows the [Agent] type(scope): description format.
"""
try:
with open(msg_file, "r") as f:
first_line = f.readline().strip()
except Exception as e:
print(f"Error reading commit message: {e}")
return False
# Skip merge commits and fixup commits
if first_line.startswith("Merge ") or first_line.startswith("fixup!"):
return True
# Pattern: [Agent] type(scope): description
pattern = r"^\[(Claude|Gemini|Codex|Human|CI)\]\s+\w+(\([^)]+\))?:\s+.+"
if not re.match(pattern, first_line, re.IGNORECASE):
print("Error: Commit message must follow format: [Agent] type(scope): description")
print(f" Got: {first_line}")
print(" Example: [Claude] feat(core): add new feature")
print(" Valid agents: Claude, Gemini, Codex, Human, CI")
return False
return True
def verify_ownership(files: List[str], agent: str, root: Path) -> Tuple[List[str], List[str]]:
"""
Verify ownership for a list of files.
Returns:
Tuple of (violations, warnings)
"""
violations = []
warnings = []
for filepath in files:
owner, ownership_type = get_file_owner(filepath)
# Unrestricted files - anyone can modify
if ownership_type == "unrestricted":
continue
# Unknown files - warn but don't block
if ownership_type == "unknown":
warnings.append(f"Unknown ownership for: {filepath}")
continue
# Shared files - warn (Claude should approve)
if ownership_type == "shared":
if agent != "claude":
warnings.append(f"Shared file modified (requires Claude approval): {filepath}")
continue
# Primary ownership check
if owner and owner != agent:
# Claude can override any ownership
if agent == "claude":
warnings.append(f"Claude overriding {owner}'s ownership: {filepath}")
else:
violations.append(f"Ownership violation: {filepath} is owned by {owner}")
# Lock check
is_locked, lock_info = is_file_locked(filepath, root)
if is_locked and lock_info:
lock_agent = lock_info.get("agent", "unknown")
if lock_agent != agent:
# Claude can override locks
if agent == "claude" and lock_info.get("lock_type") != "override":
warnings.append(f"Claude overriding {lock_agent}'s lock: {filepath}")
else:
task_id = lock_info.get("task_id", "unknown")
violations.append(f"File locked by {lock_agent}: {filepath} (task: {task_id})")
return violations, warnings
def verify_setup() -> bool:
"""Verify that the agent environment is properly configured."""
agent = get_agent_author()
root = get_project_root()
print("=== Agent Environment Verification ===\n")
# Check environment variable
if agent:
print(f"[OK] SEO_AGENT_AUTHOR is set to: {agent}")
else:
env_val = os.environ.get("SEO_AGENT_AUTHOR", "")
if env_val:
print(f"[ERROR] Invalid SEO_AGENT_AUTHOR value: {env_val}")
print(f" Valid values: {', '.join(sorted(VALID_AGENTS))}")
else:
print("[WARNING] SEO_AGENT_AUTHOR is not set")
print(" Set with: export SEO_AGENT_AUTHOR=<agent>")
# Check state files
tasks_file = root / ".agent-state" / "tasks.yaml"
locks_file = root / ".agent-state" / "locks.yaml"
if tasks_file.exists():
print(f"[OK] Tasks file exists: {tasks_file}")
else:
print(f"[WARNING] Tasks file not found: {tasks_file}")
if locks_file.exists():
print(f"[OK] Locks file exists: {locks_file}")
else:
print(f"[WARNING] Locks file not found: {locks_file}")
# Check GUARDRAILS.md
guardrails = root / "GUARDRAILS.md"
if guardrails.exists():
print("[OK] GUARDRAILS.md exists")
else:
print("[ERROR] GUARDRAILS.md not found")
print("\n=== Setup Complete ===")
return agent is not None
def list_expired(root: Path) -> None:
"""List expired tasks and locks."""
current_time = datetime.now(timezone.utc)
# Check tasks
tasks_file = root / ".agent-state" / "tasks.yaml"
tasks_data = load_yaml_file(tasks_file)
print("=== Expired Tasks ===\n")
if tasks_data and "tasks" in tasks_data:
found_expired = False
for task in tasks_data.get("tasks", []):
if not task or task.get("status") in ("completed", "abandoned"):
continue
expires_at = task.get("expires_at")
if expires_at:
try:
expiry = datetime.fromisoformat(expires_at.replace("Z", "+00:00"))
if current_time > expiry:
found_expired = True
print(f" - {task.get('id')}: {task.get('description')}")
print(f" Agent: {task.get('agent')}, Expired: {expires_at}")
except ValueError:
pass
if not found_expired:
print(" No expired tasks found.")
else:
print(" No tasks file or empty.")
# Check locks
locks_file = root / ".agent-state" / "locks.yaml"
locks_data = load_yaml_file(locks_file)
print("\n=== Expired Locks ===\n")
if locks_data and "locks" in locks_data:
found_expired = False
for lock in locks_data.get("locks", []):
if not lock:
continue
expires_at = lock.get("expires_at")
if expires_at:
try:
expiry = datetime.fromisoformat(expires_at.replace("Z", "+00:00"))
if current_time > expiry:
found_expired = True
print(f" - {lock.get('path')}")
print(f" Agent: {lock.get('agent')}, Task: {lock.get('task_id')}")
except ValueError:
pass
if not found_expired:
print(" No expired locks found.")
else:
print(" No locks file or empty.")
def validate_state(root: Path) -> bool:
"""Validate the structure of state files."""
valid = True
# Validate tasks.yaml
tasks_file = root / ".agent-state" / "tasks.yaml"
tasks_data = load_yaml_file(tasks_file)
print("=== Validating State Files ===\n")
if tasks_data:
print("[OK] tasks.yaml is valid YAML")
if "version" not in tasks_data:
print("[WARNING] tasks.yaml missing 'version' field")
if "tasks" not in tasks_data:
print("[WARNING] tasks.yaml missing 'tasks' field")
else:
if tasks_file.exists():
print("[ERROR] tasks.yaml is not valid YAML")
valid = False
else:
print("[WARNING] tasks.yaml does not exist")
# Validate locks.yaml
locks_file = root / ".agent-state" / "locks.yaml"
locks_data = load_yaml_file(locks_file)
if locks_data:
print("[OK] locks.yaml is valid YAML")
if "version" not in locks_data:
print("[WARNING] locks.yaml missing 'version' field")
if "locks" not in locks_data:
print("[WARNING] locks.yaml missing 'locks' field")
else:
if locks_file.exists():
print("[ERROR] locks.yaml is not valid YAML")
valid = False
else:
print("[WARNING] locks.yaml does not exist")
return valid
# =============================================================================
# Main Entry Point
# =============================================================================
def main() -> int:
parser = argparse.ArgumentParser(
description="Multi-Agent Ownership Verification",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("files", nargs="*", help="Files to check ownership for")
parser.add_argument(
"--check-commit-msg",
metavar="FILE",
nargs="?",
const=".git/COMMIT_EDITMSG",
help="Check commit message format",
)
parser.add_argument("--verify-setup", action="store_true", help="Verify agent environment")
parser.add_argument("--list-expired", action="store_true", help="List expired tasks/locks")
parser.add_argument(
"--validate-state", action="store_true", help="Validate state file structure"
)
parser.add_argument("--strict", action="store_true", help="Treat warnings as errors")
args = parser.parse_args()
root = get_project_root()
# Handle special commands
if args.verify_setup:
return 0 if verify_setup() else 1
if args.list_expired:
list_expired(root)
return 0
if args.validate_state:
return 0 if validate_state(root) else 1
if args.check_commit_msg:
return 0 if check_commit_message(args.check_commit_msg) else 1
# Default: check file ownership
if not args.files:
print("No files specified. Use --help for usage.")
return 0
agent = get_agent_author()
if not agent:
print("Warning: SEO_AGENT_AUTHOR not set or invalid.")
print(" Set with: export SEO_AGENT_AUTHOR=<agent>")
print(" Ownership check skipped.")
return 0
violations, warnings = verify_ownership(args.files, agent, root)
# Print results
if warnings:
print("\n=== Warnings ===")
for warning in warnings:
print(f" [WARN] {warning}")
if violations:
print("\n=== Ownership Violations ===")
for violation in violations:
print(f" [ERROR] {violation}")
print(f"\nAgent '{agent}' cannot modify these files.")
print("See GUARDRAILS.md for ownership rules.")
return 1
if args.strict and warnings:
print("\n[STRICT MODE] Treating warnings as errors.")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,327 @@
# AGENTS.md - Common Ground Rules & Collaboration Protocols
This file defines the shared rules, handoff protocols, and guidelines for all AI agents working on this repository.
> **Master Plan Reference**: For strategic decisions, roadmap, and feature priorities, consult [`PROJECT_PLAN.md`](./PROJECT_PLAN.md) if available.
> **Enforcement Layer**: For ownership rules, task claiming, and conflict resolution, see [`GUARDRAILS.md`](./GUARDRAILS.md).
## Agent Hierarchy
| Agent | Role | Authority | Context File |
|-------|------|-----------|--------------|
| **Claude Code** | Lead / Orchestrator | Architecture, core logic, final decisions | `CLAUDE.md` |
| **Gemini** | Sub-agent | Google APIs, documentation, research | `GEMINI.md` |
| **Codex** | Sub-agent | Tests, boilerplate, docstrings | `CODEX.md` |
| **Human** | Supervisor | Final approval, business decisions | N/A |
**All agents read this file (`AGENTS.md`) as the shared source of truth.**
---
## 1. Project Status
<!-- Customize this section for your project -->
| Aspect | Status | Notes |
|--------|--------|-------|
| **Stage** | [Development/Beta/Production] | |
| **Primary Language** | [Python/TypeScript/etc.] | |
| **Test Coverage** | [X%] | Target: 80% |
| **Documentation** | [Status] | See `docs/` directory |
---
## 2. Handoff Protocols
### 2.1 Claude → Gemini Handoff
**When to delegate:**
- Google API implementation (GSC, GA4, PageSpeed, etc.)
- Documentation writing (user guides, tutorials)
- Research on best practices or algorithm updates
- Content quality assessment logic
**Handoff format:**
```markdown
## Task for Gemini
**Type:** [Google API | Documentation | Research]
**Priority:** [High | Medium | Low]
### Objective
[Clear description of what needs to be done]
### Interface/Contract (if API)
```python
# Claude defines the interface
class SomeProtocol(Protocol):
async def method(...) -> SomeResponse:
...
```
### Deliverables
- [ ] Implementation file(s)
- [ ] Unit tests (optional, Codex can assist)
- [ ] Documentation updates
### Constraints
- Follow code style in AGENTS.md Section 4
- Use existing patterns from the codebase
```
**Return protocol:**
Gemini returns completed code → Claude reviews → Claude integrates.
---
### 2.2 Claude → Codex Handoff
**When to delegate:**
- Unit test generation from existing code
- Boilerplate Pydantic/dataclass models
- Docstring generation
- Repetitive pattern implementation
**Handoff format:**
```markdown
## Task for Codex
**Type:** [Tests | Models | Docstrings | Boilerplate]
### Pattern to Follow
```python
# Claude provides the first example
class ExampleClass(BaseClass):
def method(self, arg: str) -> Result:
...
```
### Generate
- [ ] SimilarClass1 (same pattern)
- [ ] SimilarClass2 (same pattern)
- [ ] Tests for all classes
```
**Return protocol:**
Codex generates → Claude reviews for edge cases → Claude commits.
---
### 2.3 Sub-agent → Claude Escalation
**When to escalate back:**
- Complex error handling needed
- Multi-file integration required
- Architectural decisions needed
- Rate limiting / caching strategy
**Escalation format:**
```markdown
## Escalation to Claude
**Reason:** [Complexity | Architecture | Integration]
### Completed Work
[What was finished]
### Blocking Issue
[What requires Claude's decision]
### Proposed Options
1. Option A: ...
2. Option B: ...
```
---
## 3. Development Workflow
> **Task Claiming**: Before starting work, claim your task in `.agent-state/tasks.yaml`.
> See [`GUARDRAILS.md`](./GUARDRAILS.md) for the full claiming protocol.
### Phase 1: Planning (Claude Lead)
```
User Request → Claude analyzes
Claude creates task breakdown
Claude assigns to agents
Claude defines interfaces
```
### Phase 2: Implementation (Parallel)
```
┌─────────────┬─────────────┬─────────────┐
│ Claude │ Gemini │ Codex │
├─────────────┼─────────────┼─────────────┤
│ Core logic │ Google APIs │ Tests │
│ Complex │ Docs │ Models │
│ Integration │ Research │ Docstrings │
└─────────────┴─────────────┴─────────────┘
```
**Before modifying files:**
1. Set `SEO_AGENT_AUTHOR` environment variable
2. Check `.agent-state/locks.yaml` for active locks
3. Claim task in `.agent-state/tasks.yaml`
### Phase 3: Review & Merge (Claude Lead)
```
Sub-agent work → Claude reviews
Claude integrates
Claude runs full test suite
Claude commits with attribution
```
---
## 4. Code Style Guidelines
### 4.1 Python Conventions
| Rule | Standard |
|------|----------|
| Line length | 100 characters |
| Formatter | Black |
| Import sorter | isort (Black profile) |
| Linter | flake8 |
| Type checker | mypy |
| Docstrings | Google-style |
### 4.2 Import Organization
```python
# Standard library
import asyncio
import logging
from typing import Dict, List, Optional
# Third-party
import aiohttp
from pydantic import BaseModel
# Local
from mypackage.models import MyModel
from mypackage.utils import helper_function
```
### 4.3 Error Handling Pattern
```python
try:
result = await some_operation(arg)
except SpecificError as e:
logger.warning(f"Specific error: {e}")
return None
except GeneralError:
logger.exception("Unexpected error")
raise
```
---
## 5. Commit & PR Standards
### 5.1 Commit Message Format
```
[Agent] type(scope): description
Body explaining the change (optional)
Co-Authored-By: Claude <noreply@anthropic.com>
```
**Types:** `feat`, `fix`, `docs`, `test`, `refactor`, `chore`
**Agent tags:** `[Claude]`, `[Gemini]`, `[Codex]`, `[Human]`, `[CI]`
### 5.2 Examples
```bash
[Claude] feat(core): implement new feature
[Gemini] docs(api): add API documentation
[Codex] test(models): add unit tests for models
[Human] fix(config): update configuration
```
### 5.3 PR Checklist
```markdown
## Pre-Merge Checklist
- [ ] Tests pass
- [ ] Code quality passes (formatter, linter, type checker)
- [ ] No hardcoded secrets
- [ ] Error handling implemented
- [ ] Logging added for debugging
- [ ] Documentation updated
- [ ] Agent attribution in commit messages
```
---
## 6. Quality Assurance
### 6.1 Review Matrix
| Review Type | Reviewer | Focus |
|-------------|----------|-------|
| Architecture | Claude | Design patterns, scalability |
| Logic correctness | Claude | Edge cases, error handling |
| Google API usage | Gemini | Best practices, quotas |
| Code style | Linter | Consistency |
| Documentation | Gemini | Clarity, completeness |
| Test coverage | Claude + Codex | Coverage, edge cases |
### 6.2 Testing Standards
```bash
# Minimum requirements before merge
pytest --cov=src --cov-fail-under=70
# For critical modules
pytest --cov=src/critical_module --cov-fail-under=80
```
---
## 7. Quick Reference Commands
```bash
# Quality checks
black src tests && isort src tests && flake8 src tests && mypy src tests
# Testing
pytest # All tests
pytest tests/test_file.py -v # Single file
pytest -k "pattern" -v # Pattern match
pytest --cov=src --cov-report=html # Coverage report
```
---
## 8. References
### Internal Documents
| Document | Purpose |
|----------|---------|
| [`GUARDRAILS.md`](./GUARDRAILS.md) | Ownership, locks, conflict resolution |
| [`CLAUDE.md`](./CLAUDE.md) | Lead agent directive |
| [`GEMINI.md`](./GEMINI.md) | Gemini sub-agent directive |
| [`CODEX.md`](./CODEX.md) | Codex sub-agent directive |
---
*This document is the shared source of truth for all AI agents. Claude Code maintains and updates this file.*
*Last updated: [DATE]*

View File

@@ -0,0 +1,141 @@
# CLAUDE.md - Project Lead & Orchestrator
This file defines Claude Code's role as the **Lead AI Agent** for this project.
## Role: Project Manager & Architect
Claude Code serves as the primary orchestrator for this repository, responsible for:
| Domain | Responsibilities |
|--------|------------------|
| **Architecture** | System design, module structure, data flow decisions |
| **Orchestration** | Task delegation to sub-agents, workflow coordination |
| **Core Logic** | Complex algorithms, business logic, error handling |
| **Version Control** | Git management, branching strategy, PR reviews, commit standards |
| **Quality Gate** | Code review authority, merge decisions, release management |
| **Integration** | MCP server configuration, external API orchestration |
## Sub-Agent Hierarchy
```
┌─────────────────┐
│ Claude Code │
│ (Lead Agent) │
└────────┬────────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Gemini │ │ Codex │ │ Human │
│(Research)│ │ (Speed) │ │ (Review) │
└──────────┘ └──────────┘ └──────────┘
```
- **Gemini**: Google APIs, documentation, research tasks
- **Codex**: Boilerplate, tests, docstrings, repetitive patterns
- **Human**: Final approval, business decisions, priority setting
## Project Overview
<!-- Customize this section for your project -->
| Aspect | Details |
|--------|---------|
| Status | [Development/Beta/Production] |
| Language | [Python/TypeScript/etc.] |
| CLI | [Your CLI command] |
| Source | [Main source directory] |
## Quick Commands
```bash
# Install
pip install -e ".[dev]"
# Run
[your-cli] --help
# Test & Quality
pytest --cov=src --cov-report=term-missing
black src tests && isort src tests && flake8 src tests
```
## Architecture Overview
### Core Modules
<!-- Customize for your project structure -->
| Module | Purpose | Complexity |
|--------|---------|------------|
| `cli.py` | CLI entry point | High |
| `core.py` | Core business logic | High |
| `models.py` | Data models | Low |
| `utils.py` | Helper functions | Low |
## Orchestration Patterns
### When to Delegate
| Task Type | Delegate To | Example |
|-----------|-------------|---------|
| Google API implementation | Gemini | OAuth, API clients |
| Documentation writing | Gemini | User guides, API docs |
| Unit test generation | Codex | pytest cases |
| Boilerplate models | Codex | Pydantic schemas |
| Complex refactoring | Keep (Claude) | Multi-file restructuring |
| Architecture decisions | Keep (Claude) | New module design |
### Handoff Protocol
See `AGENTS.md` for detailed handoff procedures between agents.
## Git Management
### Branching Strategy
```
main ─────────────────────────────────────────▶
└── feature/xxx ──── PR ──── merge ─────────▶
└── fix/xxx ──────── PR ──── merge ─────────▶
```
### Commit Convention
```
[Agent] type(scope): description
[Claude] feat(core): add new feature
[Gemini] docs(api): update API documentation
[Codex] test(models): add model tests
[Human] fix(config): correct configuration
```
### PR Requirements
- [ ] Tests pass
- [ ] Code quality passes (formatter, linter, type checker)
- [ ] Documentation updated if needed
- [ ] Sub-agent contributions attributed in commit messages
## Code Standards
- **Line length:** 100 chars
- **Formatter:** Black + isort (Python) / Prettier (JS)
- **Type hints:** Required for all signatures
- **Docstrings:** Google-style
## Related Documentation
| File | Purpose |
|------|---------|
| `AGENTS.md` | Common ground rules, handoff protocols |
| `GUARDRAILS.md` | Ownership, locks, conflict resolution |
| `GEMINI.md` | Gemini sub-agent directive |
| `CODEX.md` | Codex sub-agent directive |
---
*Claude Code is the authoritative source for architectural decisions in this repository.*

View File

@@ -0,0 +1,215 @@
# CODEX.md - Testing & Boilerplate Sub-Agent
This file defines Codex's role as a **Sub-Agent** specializing in testing, models, and repetitive patterns.
## Role: Testing & Boilerplate Specialist
Codex serves as a specialized agent for:
| Domain | Responsibilities |
|--------|------------------|
| **Testing** | Unit tests, integration tests, test fixtures |
| **Models** | Pydantic models, dataclasses, type definitions |
| **Docstrings** | Google-style documentation for functions |
| **Boilerplate** | Repetitive patterns, similar class implementations |
## Hierarchy Position
```
┌─────────────────┐
│ Claude Code │ ← Lead Agent
│ (Orchestrator) │
└────────┬────────┘
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Gemini │ │ Codex │ │ Human │
│ │ │ (YOU) │ │ │
└──────────┘ └──────────┘ └──────────┘
```
## Primary Ownership
| Pattern | Description |
|---------|-------------|
| `CODEX.md` | This directive file |
| `tests/` | All test files |
| `src/*/models.py` | Data models |
| `src/*/utils/` | Utility functions |
## Workflow
### Receiving Tasks from Claude
Claude will delegate tasks using this format:
```markdown
## Task for Codex
**Type:** [Tests | Models | Docstrings | Boilerplate]
### Pattern to Follow
```python
# Claude provides the first example
class ExampleClass(BaseClass):
def method(self, arg: str) -> Result:
...
```
### Generate
- [ ] SimilarClass1 (same pattern)
- [ ] SimilarClass2 (same pattern)
- [ ] Tests for all classes
```
### Completing Tasks
1. **Claim task** in `.agent-state/tasks.yaml`
2. **Acquire locks** for files you'll modify
3. **Generate** following Claude's pattern
4. **Test** your implementation
5. **Return to Claude** for review
### Escalation to Claude
Escalate back to Claude when:
- Logic beyond simple patterns
- Complex mocking or fixtures needed
- Unclear requirements
```markdown
## Escalation to Claude
**Reason:** [Complexity | Unclear | Dependencies]
### Completed Work
[What you finished]
### Question
[What you need clarification on]
```
## Code Standards
Follow these standards:
| Standard | Value |
|----------|-------|
| Line length | 100 characters |
| Formatter | Black (Python) |
| Test framework | pytest |
| Type hints | Required |
### Example Test Style
```python
import pytest
from mypackage.models import MyModel
class TestMyModel:
"""Tests for MyModel class."""
@pytest.fixture
def sample_data(self) -> dict:
"""Provide sample data for tests."""
return {
"name": "test",
"value": 42,
}
def test_creation(self, sample_data: dict) -> None:
"""Test model creation with valid data."""
model = MyModel(**sample_data)
assert model.name == "test"
assert model.value == 42
def test_validation_error(self) -> None:
"""Test model raises error on invalid data."""
with pytest.raises(ValueError):
MyModel(name="", value=-1)
@pytest.mark.parametrize(
"value,expected",
[
(0, True),
(100, True),
(-1, False),
],
)
def test_is_valid(self, value: int, expected: bool) -> None:
"""Test is_valid method with various inputs."""
model = MyModel(name="test", value=value)
assert model.is_valid() == expected
```
### Example Model Style
```python
from typing import Optional
from pydantic import BaseModel, Field, validator
class MyModel(BaseModel):
"""
Represents a data entity.
Attributes:
name: The entity name
value: The numeric value
description: Optional description
"""
name: str = Field(..., min_length=1, description="Entity name")
value: int = Field(..., ge=0, description="Numeric value")
description: Optional[str] = Field(None, description="Optional description")
@validator("name")
def validate_name(cls, v: str) -> str:
"""Ensure name is properly formatted."""
return v.strip()
def is_valid(self) -> bool:
"""Check if the model data is valid."""
return self.value >= 0
```
## Commit Format
Always use this commit format:
```
[Codex] type(scope): description
Examples:
[Codex] test(models): add unit tests for MyModel
[Codex] feat(models): add NewModel with validation
[Codex] refactor(utils): add type hints to helpers
```
## Before Starting Work
1. Set environment variable:
```bash
export SEO_AGENT_AUTHOR=codex
```
2. Check for existing locks:
```bash
python tools/check-ownership.py --list-expired
```
3. Claim your task in `.agent-state/tasks.yaml`
## References
| Document | Purpose |
|----------|---------|
| `AGENTS.md` | Collaboration rules |
| `GUARDRAILS.md` | Ownership matrix |
| `CLAUDE.md` | Lead agent directive |
---
*Codex operates under Claude Code's orchestration. Always follow the provided patterns exactly.*

View File

@@ -0,0 +1,165 @@
# GEMINI.md - Research & Documentation Sub-Agent
This file defines Gemini's role as a **Sub-Agent** specializing in documentation, Google APIs, and research.
## Role: Research & Documentation Specialist
Gemini serves as a specialized agent for:
| Domain | Responsibilities |
|--------|------------------|
| **Google APIs** | GSC, GA4, PageSpeed, OAuth implementation |
| **Documentation** | User guides, API docs, tutorials |
| **Research** | Best practices, algorithm updates, industry trends |
| **Content** | Technical writing, explanations |
## Hierarchy Position
```
┌─────────────────┐
│ Claude Code │ ← Lead Agent
│ (Orchestrator) │
└────────┬────────┘
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Gemini │ │ Codex │ │ Human │
│ (YOU) │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘
```
## Primary Ownership
| Pattern | Description |
|---------|-------------|
| `GEMINI.md` | This directive file |
| `src/*/integrations/google/` | Google API integrations |
| `src/*/integrations/gsc.py` | Google Search Console |
| `src/*/integrations/ga*.py` | Google Analytics |
| `docs/*.md` | Documentation files |
## Workflow
### Receiving Tasks from Claude
Claude will delegate tasks using this format:
```markdown
## Task for Gemini
**Type:** [Google API | Documentation | Research]
**Priority:** [High | Medium | Low]
### Objective
[What needs to be done]
### Deliverables
- [ ] Item 1
- [ ] Item 2
```
### Completing Tasks
1. **Claim task** in `.agent-state/tasks.yaml`
2. **Acquire locks** for files you'll modify
3. **Implement** following Claude's specifications
4. **Test** your implementation
5. **Return to Claude** with completion report
### Escalation to Claude
Escalate back to Claude when:
- Complex error handling needed
- Multi-file integration required
- Architectural decisions needed
```markdown
## Escalation to Claude
**Reason:** [Complexity | Architecture | Integration]
### Completed Work
[What you finished]
### Blocking Issue
[What requires Claude's decision]
```
## Code Standards
Follow these standards when writing code:
| Standard | Value |
|----------|-------|
| Line length | 100 characters |
| Formatter | Black (Python) |
| Type hints | Required |
| Docstrings | Google-style |
### Example Code Style
```python
async def get_search_analytics(
self,
site_url: str,
start_date: str,
end_date: str,
dimensions: Optional[List[str]] = None,
) -> SearchAnalyticsResponse:
"""
Fetch search analytics data from Google Search Console.
Args:
site_url: The site URL to query
start_date: Start date in YYYY-MM-DD format
end_date: End date in YYYY-MM-DD format
dimensions: Optional list of dimensions
Returns:
SearchAnalyticsResponse containing the analytics data
Raises:
GSCError: If the API request fails
"""
...
```
## Commit Format
Always use this commit format:
```
[Gemini] type(scope): description
Examples:
[Gemini] feat(gsc): implement search analytics endpoint
[Gemini] docs(api): add GSC integration guide
[Gemini] fix(oauth): correct token refresh logic
```
## Before Starting Work
1. Set environment variable:
```bash
export SEO_AGENT_AUTHOR=gemini
```
2. Check for existing locks:
```bash
python tools/check-ownership.py --list-expired
```
3. Claim your task in `.agent-state/tasks.yaml`
## References
| Document | Purpose |
|----------|---------|
| `AGENTS.md` | Collaboration rules |
| `GUARDRAILS.md` | Ownership matrix |
| `CLAUDE.md` | Lead agent directive |
---
*Gemini operates under Claude Code's orchestration. Always coordinate major changes with Claude.*

View File

@@ -0,0 +1,161 @@
# GitHub Actions Workflow: Ownership Check
# Save as: .github/workflows/ownership-check.yml
#
# This workflow verifies file ownership rules on pull requests.
name: Ownership Check
on:
pull_request:
branches: [main, develop]
types: [opened, synchronize, reopened]
jobs:
check-ownership:
name: Verify File Ownership
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Full history for accurate diff
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Install dependencies
run: pip install pyyaml
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
- name: Check ownership
id: ownership-check
env:
SEO_AGENT_AUTHOR: ci
run: |
echo "Changed files: ${{ steps.changed-files.outputs.all_changed_files }}"
# Run ownership check
python tools/check-ownership.py ${{ steps.changed-files.outputs.all_changed_files }} > ownership_result.txt 2>&1 || true
# Capture exit code
python tools/check-ownership.py ${{ steps.changed-files.outputs.all_changed_files }}
echo "exit_code=$?" >> $GITHUB_OUTPUT
# Show results
cat ownership_result.txt
- name: Check commit messages
run: |
# Get commits in PR
commits=$(git log origin/${{ github.base_ref }}..HEAD --format="%H")
for commit in $commits; do
msg=$(git log -1 --format="%s" $commit)
echo "Checking commit: $msg"
# Check format: [Agent] type(scope): description
if ! echo "$msg" | grep -qE "^\[(Claude|Gemini|Codex|Human|CI)\] \w+(\([^)]+\))?: .+"; then
echo "::error::Invalid commit message format: $msg"
echo "Expected format: [Agent] type(scope): description"
exit 1
fi
done
echo "All commit messages are valid."
- name: Comment on PR (violations)
if: failure()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
let result = '';
try {
result = fs.readFileSync('ownership_result.txt', 'utf8');
} catch (e) {
result = 'Unable to read ownership check results.';
}
const body = `## Ownership Check Failed
The following ownership violations were detected:
\`\`\`
${result}
\`\`\`
Please ensure:
1. You are modifying files in your agent's ownership domain
2. Shared files have Claude's approval
3. Commit messages follow the format: \`[Agent] type(scope): description\`
See \`GUARDRAILS.md\` for ownership rules.
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
- name: Comment on PR (success)
if: success()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '✅ **Ownership Check Passed**\n\nAll file ownership rules and commit message formats are valid.'
});
validate-state-files:
name: Validate Agent State Files
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Validate YAML files
run: |
python -c "
import yaml
import sys
files = ['.agent-state/tasks.yaml', '.agent-state/locks.yaml']
errors = []
for f in files:
try:
with open(f, 'r') as file:
data = yaml.safe_load(file)
if data is None:
errors.append(f'{f}: File is empty')
elif 'version' not in data:
print(f'Warning: {f} missing version field')
except FileNotFoundError:
print(f'Warning: {f} not found')
except yaml.YAMLError as e:
errors.append(f'{f}: Invalid YAML - {e}')
if errors:
for e in errors:
print(f'Error: {e}')
sys.exit(1)
print('All state files are valid.')
"

View File

@@ -0,0 +1,355 @@
# GUARDRAILS.md - Ownership & Enforcement Rules
This document defines the ownership matrix, lock system, and enforcement mechanisms for multi-agent collaboration in this repository.
> **Collaboration Rules**: See [`AGENTS.md`](./AGENTS.md) for handoff protocols and code standards.
---
## 1. Ownership Matrix
### 1.1 Ownership Categories
| Category | Description | Override |
|----------|-------------|----------|
| **Primary** | Agent has exclusive authority | Claude can override |
| **Shared** | Multiple agents can modify, requires coordination | Claude approves changes |
| **Unrestricted** | Any agent can modify | No restrictions |
### 1.2 Claude Code - Primary Ownership
Claude Code is the lead agent with primary ownership of:
| Pattern | Description |
|---------|-------------|
| `CLAUDE.md` | Lead agent directive |
| `AGENTS.md` | Shared collaboration rules |
| `GUARDRAILS.md` | This file |
| `src/*/cli.py` | CLI entry points |
| `src/*/core/` | Core logic modules |
| `src/*/main.py` | Main entry points |
### 1.3 Gemini - Primary Ownership
Gemini has primary ownership of:
| Pattern | Description |
|---------|-------------|
| `GEMINI.md` | Gemini directive |
| `src/*/integrations/google/` | Google API integrations |
| `src/*/integrations/gsc.py` | Google Search Console |
| `src/*/integrations/ga*.py` | Google Analytics |
| `docs/` | Documentation (markdown) |
### 1.4 Codex - Primary Ownership
Codex has primary ownership of:
| Pattern | Description |
|---------|-------------|
| `CODEX.md` | Codex directive |
| `src/*/models.py` | Pydantic/data models |
| `src/*/utils/` | Utility functions |
| `tests/` | All test files |
### 1.5 Shared Files
These files require coordination (Claude approves):
| Pattern | Coordination Rule |
|---------|-------------------|
| `pyproject.toml` | Dependency changes require discussion |
| `config/*.yaml` | Configuration changes affect all agents |
| `.github/workflows/` | CI/CD changes impact everyone |
| `PROJECT_PLAN.md` | Roadmap changes need consensus |
### 1.6 Unrestricted Files
Any agent can modify these files:
| Pattern | Notes |
|---------|-------|
| `.agent-state/` | Task and lock management |
| `.gitignore` | Git configuration |
| `README.md` | Project readme |
| `.pre-commit-config.yaml` | Pre-commit hooks |
---
## 2. Lock System
### 2.1 Lock Types
| Type | Description | Use Case |
|------|-------------|----------|
| `exclusive` | Single agent can modify | Long-running refactors |
| `shared` | Multiple can read, one writes | Concurrent development |
| `override` | Claude override for conflicts | Emergency fixes |
### 2.2 Lock File Format
Location: `.agent-state/locks.yaml`
```yaml
version: "1.0"
updated_at: "2025-01-29T12:00:00Z"
locks:
- path: "src/module/"
agent: "claude"
lock_type: "exclusive"
task_id: "TASK-001"
reason: "Refactoring core module"
created_at: "2025-01-29T10:00:00Z"
expires_at: "2025-01-29T14:00:00Z"
- path: "docs/api/"
agent: "gemini"
lock_type: "shared"
task_id: "TASK-002"
reason: "Updating API documentation"
created_at: "2025-01-29T11:00:00Z"
expires_at: "2025-01-29T15:00:00Z"
```
### 2.3 Lock Operations
**Acquire Lock:**
1. Check if path is already locked
2. If locked by another agent, wait or request release
3. Add lock entry to locks.yaml
4. Set expiration time (default: 4 hours)
**Release Lock:**
1. Remove lock entry from locks.yaml
2. Update `updated_at` timestamp
3. Notify other agents if requested
**Lock Expiration:**
- Locks automatically expire at `expires_at` time
- Expired locks can be claimed by any agent
- Run `python tools/check-ownership.py --list-expired` to see expired locks
---
## 3. Task Claiming Protocol
### 3.1 Task File Format
Location: `.agent-state/tasks.yaml`
```yaml
version: "1.0"
updated_at: "2025-01-29T12:00:00Z"
tasks:
- id: "TASK-001"
description: "Implement new feature"
agent: "claude"
status: "in_progress"
priority: "high"
files:
- "src/feature.py"
- "tests/test_feature.py"
created_at: "2025-01-29T09:00:00Z"
claimed_at: "2025-01-29T09:30:00Z"
expires_at: "2025-01-29T13:30:00Z"
- id: "TASK-002"
description: "Write API documentation"
agent: "gemini"
status: "pending"
priority: "medium"
files:
- "docs/api.md"
created_at: "2025-01-29T10:00:00Z"
```
### 3.2 Task Status Flow
```
pending → in_progress → completed
abandoned (if expired)
blocked (if dependency)
```
### 3.3 Claiming Process
1. **Check availability**: Verify task is `pending`
2. **Set identity**: Ensure `SEO_AGENT_AUTHOR` is set
3. **Claim task**: Update tasks.yaml with your agent name
4. **Acquire locks**: Lock files you'll modify
5. **Begin work**: Start implementation
6. **Complete task**: Mark as `completed`, release locks
### 3.4 Task Expiration
- Default timeout: 4 hours from `claimed_at`
- Expired tasks revert to `pending`
- Other agents can reclaim expired tasks
---
## 4. Environment Configuration
### 4.1 Required Environment Variable
```bash
# Set in shell profile or .envrc
export SEO_AGENT_AUTHOR=<agent_name>
# Valid values:
# - claude
# - gemini
# - codex
# - human
```
### 4.2 Verification
```bash
# Check current agent identity
echo $SEO_AGENT_AUTHOR
# Verify setup
python tools/check-ownership.py --verify-setup
```
---
## 5. Conflict Resolution
### 5.1 Resolution Hierarchy
| Conflict Type | Resolution |
|---------------|------------|
| Ownership dispute | Claude decides |
| Lock conflict | First to lock wins; Claude can override |
| Task overlap | Split tasks or assign to single agent |
| Merge conflict | Claude resolves |
### 5.2 Escalation Process
1. **Identify conflict**: Agent detects violation
2. **Document issue**: Add to escalation log
3. **Notify Claude**: Include conflict details
4. **Claude decides**: Makes binding decision
5. **Update rules**: Modify GUARDRAILS.md if pattern emerges
### 5.3 Claude Override
Claude can override any lock or ownership rule:
```yaml
# In locks.yaml
- path: "src/critical/"
agent: "claude"
lock_type: "override"
task_id: "EMERGENCY-001"
reason: "Critical bug fix"
override_agent: "gemini" # Agent whose lock was overridden
```
---
## 6. Verification Tools
### 6.1 check-ownership.py Commands
```bash
# Verify files before commit
python tools/check-ownership.py path/to/file.py
# Check commit message format
python tools/check-ownership.py --check-commit-msg
# Verify setup
python tools/check-ownership.py --verify-setup
# List expired locks/tasks
python tools/check-ownership.py --list-expired
# Validate state files
python tools/check-ownership.py --validate-state
# Strict mode (warnings as errors)
python tools/check-ownership.py --strict path/to/file.py
```
### 6.2 Pre-commit Integration
The following hooks run automatically:
| Hook | Stage | Purpose |
|------|-------|---------|
| `check-ownership` | commit | Verify file ownership |
| `check-commit-message` | commit-msg | Validate message format |
---
## 7. CI/CD Integration
### 7.1 GitHub Actions
Ownership checks run on PRs:
```yaml
# .github/workflows/ownership-check.yml
- Check changed files against ownership matrix
- Post violations as PR comments
- Block merge on violations
```
### 7.2 PR Labels
| Label | Meaning |
|-------|---------|
| `ownership-verified` | All files verified |
| `ownership-override` | Claude approved override |
| `ownership-violation` | Needs resolution |
---
## 8. Quick Reference
### Commands
```bash
# Set identity
export SEO_AGENT_AUTHOR=claude
# Check ownership
python tools/check-ownership.py src/file.py
# List expired
python tools/check-ownership.py --list-expired
# Validate state
python tools/check-ownership.py --validate-state
```
### Commit Format
```
[Agent] type(scope): description
[Claude] feat(core): implement new feature
[Gemini] docs(api): update API documentation
[Codex] test(models): add model tests
```
### File Locations
| File | Purpose |
|------|---------|
| `.agent-state/tasks.yaml` | Task registry |
| `.agent-state/locks.yaml` | Lock registry |
| `tools/check-ownership.py` | Verification script |
---
*This document defines the enforcement rules for multi-agent collaboration. Claude Code is the authoritative source for conflict resolution.*
*Last updated: [DATE]*

View File

@@ -0,0 +1,42 @@
# Agent File Locks Registry
# Location: .agent-state/locks.yaml
#
# This file tracks file/directory locks held by agents.
# Agents must acquire locks before modifying files.
version: "1.0"
updated_at: "2025-01-29T00:00:00Z"
# Lock Types:
# - exclusive: Only one agent can modify (blocks all others)
# - shared: Multiple can read, one can write
# - override: Claude override for conflict resolution
locks: []
# Example lock entry:
#
# locks:
# - path: "src/core/"
# agent: "claude"
# lock_type: "exclusive"
# task_id: "TASK-001"
# reason: "Refactoring core module"
# created_at: "2025-01-29T10:00:00Z"
# expires_at: "2025-01-29T14:00:00Z"
#
# - path: "docs/api/"
# agent: "gemini"
# lock_type: "shared"
# task_id: "TASK-002"
# reason: "Updating API documentation"
# created_at: "2025-01-29T11:00:00Z"
# expires_at: "2025-01-29T15:00:00Z"
#
# - path: "tests/"
# agent: "codex"
# lock_type: "exclusive"
# task_id: "TASK-003"
# reason: "Adding comprehensive tests"
# created_at: "2025-01-29T12:00:00Z"
# expires_at: "2025-01-29T16:00:00Z"

View File

@@ -0,0 +1,90 @@
# Pre-commit Configuration for Multi-Agent Projects
# Save as: .pre-commit-config.yaml (update existing or create new)
#
# Install: pre-commit install
# Run all: pre-commit run --all-files
repos:
# Standard pre-commit hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
exclude: ^\.agent-state/
- id: end-of-file-fixer
exclude: ^\.agent-state/
- id: check-yaml
args: [--unsafe] # Allow custom tags in YAML
- id: check-json
- id: check-toml
- id: check-merge-conflict
- id: check-added-large-files
args: ['--maxkb=500']
- id: detect-private-key
- id: no-commit-to-branch
args: ['--branch', 'main']
# Python code formatting (if using Python)
- repo: https://github.com/psf/black
rev: 24.1.1
hooks:
- id: black
args: ['--line-length=100']
language_version: python3
# Import sorting (if using Python)
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
args: ['--profile=black', '--line-length=100']
# Linting (if using Python)
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
args: ['--max-line-length=100', '--extend-ignore=E203,W503']
# Custom multi-agent hooks
- repo: local
hooks:
# Ownership verification hook
- id: check-ownership
name: Check Agent Ownership
description: Verify file ownership and locks for multi-agent workflow
entry: python tools/check-ownership.py
language: python
always_run: true
pass_filenames: true
additional_dependencies:
- pyyaml
# Only runs when SEO_AGENT_AUTHOR is set
# If not set, hook will warn but not block
# Commit message format hook
- id: check-commit-message
name: Check Commit Message Format
description: Verify commit message follows [Agent] type(scope) format
entry: python tools/check-ownership.py --check-commit-msg
language: python
stages: [commit-msg]
additional_dependencies:
- pyyaml
# CI Configuration
# These settings are used when running in CI environment
ci:
autofix_commit_msg: |
[CI] auto fixes from pre-commit hooks
for more information, see https://pre-commit.ci
autofix_prs: true
autoupdate_branch: ''
autoupdate_commit_msg: '[CI] pre-commit autoupdate'
autoupdate_schedule: weekly
skip: [check-ownership, check-commit-message] # Skip custom hooks in CI
submodules: false
# Default stages - hooks run at these stages unless otherwise specified
default_stages: [commit]

View File

@@ -0,0 +1,48 @@
# Agent Tasks Registry
# Location: .agent-state/tasks.yaml
#
# This file tracks all tasks claimed by agents.
# Agents must claim tasks before modifying associated files.
version: "1.0"
updated_at: "2025-01-29T00:00:00Z"
# Task Status Values:
# - pending: Available for claiming
# - in_progress: Currently being worked on
# - completed: Work finished successfully
# - abandoned: Work stopped, task available for reclaiming
# - blocked: Waiting on dependencies
tasks: []
# Example task entry:
#
# tasks:
# - id: "TASK-001"
# description: "Implement new feature"
# agent: "claude"
# status: "in_progress"
# priority: "high"
# files:
# - "src/feature.py"
# - "tests/test_feature.py"
# depends_on: []
# created_at: "2025-01-29T09:00:00Z"
# claimed_at: "2025-01-29T09:30:00Z"
# expires_at: "2025-01-29T13:30:00Z"
# completed_at: null
#
# - id: "TASK-002"
# description: "Write API documentation"
# agent: null
# status: "pending"
# priority: "medium"
# files:
# - "docs/api.md"
# depends_on:
# - "TASK-001"
# created_at: "2025-01-29T10:00:00Z"
# claimed_at: null
# expires_at: null
# completed_at: null