Stack-2-9-finetuned / stack /internal /CONTRIBUTING.md
walidsobhie-code
refactor: Squeeze folders further - cleaner structure
65888d5
# Contributing to Stack 2.9
Thank you for your interest in contributing to Stack 2.9! This document provides guidelines and instructions for contributing to the project.
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Setup](#development-setup)
- [Code Style](#code-style)
- [Making Changes](#making-changes)
- [Submitting Pull Requests](#submitting-pull-requests)
- [Writing Tests](#writing-tests)
- [Documentation Guidelines](#documentation-guidelines)
- [Bug Reports](#bug-reports)
- [Feature Requests](#feature-requests)
---
## Code of Conduct
By participating in this project, you agree to maintain a respectful and inclusive environment for everyone.
**Our Standards:**
- Be kind and respectful in all interactions
- Accept constructive criticism gracefully
- Focus on what is best for the community
- Show empathy towards other community members
**Unacceptable Behavior:**
- Harassment, discrimination, or intimidation
- Personal attacks or derogatory remarks
- Publishing others' private information without permission
- Other conduct that could reasonably be considered inappropriate
---
## Getting Started
### Fork the Repository
1. Fork the repository on GitHub
2. Clone your fork locally:
```bash
git clone https://github.com/YOUR_USERNAME/stack-2.9.git
cd stack-2.9
# Add upstream remote
git remote add upstream https://github.com/openclaw/stack-2.9.git
```
### Stay Updated
```bash
# Fetch latest changes from upstream
git fetch upstream
# Merge into your main branch
git checkout main
git merge upstream/main
# Update your feature branch
git checkout your-feature-branch
git rebase main
```
---
## Development Setup
### Prerequisites
- Python 3.8+ (3.11+ recommended)
- Node.js 18+ (20 LTS recommended)
- Git
- GPU for model-related testing (optional but recommended)
### Environment Setup
```bash
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txt
# Install development dependencies
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install
# Install Node.js dependencies (for voice features)
npm install
```
### Verify Installation
```bash
# Run tests
pytest
# Check code formatting
make lint
# Run type checking
mypy stack_cli/
```
### IDE Setup
**VS Code:**
```json
// .vscode/settings.json
{
"python.defaultInterpreterPath": ".venv/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"editor.rulers": [100],
"files.exclude": {
"**/__pycache__": true,
"**/*.pyc": true,
".venv": true
}
}
```
**PyCharm:**
1. Settings → Project → Python Interpreter → Add → Existing Environment
2. Select `.venv/bin/python`
3. Enable Black for formatting in Settings → Python → Formatting → Black
---
## Code Style
### Python
We follow PEP 8 with some modifications:
- Line length: 100 characters (not 79)
- Use type hints where possible
- Docstrings for all public functions and classes
**Style Guide:**
```python
"""
Module docstring describing the module's purpose.
"""
from typing import List, Optional, Dict
from dataclasses import dataclass
@dataclass
class ExampleClass:
"""Class docstring describing the class.
Attributes:
name: The name of the example.
value: The value of the example.
"""
name: str
value: int
def __post_init__(self):
"""Validate after initialization."""
if self.value < 0:
raise ValueError("Value must be non-negative")
def process(self, data: List[str]) -> Dict[str, int]:
"""Process data and return results.
Args:
data: List of strings to process.
Returns:
Dictionary mapping strings to their lengths.
Raises:
ValueError: If data is empty.
"""
if not data:
raise ValueError("Data cannot be empty")
return {item: len(item) for item in data}
```
### JavaScript/TypeScript
```typescript
/**
* Interface for a user configuration.
*/
interface UserConfig {
/** User's display name */
name: string;
/** User's email address */
email: string;
/** Whether the user is enabled */
enabled: boolean;
}
/**
* Process user configuration and return formatted string.
*
* @param config - The user configuration
* @returns Formatted configuration string
*/
export function formatConfig(config: UserConfig): string {
const { name, email, enabled } = config;
if (!enabled) {
return `${name} (disabled)`;
}
return `${name} <${email}>`;
}
```
### Shell Scripts
```bash
#!/usr/bin/env bash
set -euo pipefail
# Constant for the application name
readonly APP_NAME="stack-2.9"
readonly LOG_DIR="/var/log/${APP_NAME}"
# Main function
main() {
log "Starting ${APP_NAME}..."
# Implementation here
}
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
# Run main
main "$@"
```
---
## Making Changes
### Create a Branch
```bash
# Start from an updated main branch
git checkout main
git pull upstream main
# Create a new feature branch
git checkout -b feature/your-feature-name
# Or for bug fixes
git checkout -b fix/issue-number-description
# Or for documentation
git checkout -b docs/improvement-description
```
### Branch Naming Conventions
| Type | Pattern | Example |
|------|---------|---------|
| Feature | `feature/<description>` | `feature/voice-integration` |
| Bug Fix | `fix/<issue>-<description>` | `fix/123-memory-leak` |
| Documentation | `docs/<description>` | `docs/api-reference` |
| Refactoring | `refactor/<description>` | `refactor/tool-execution` |
| Testing | `test/<description>` | `test/improve-coverage` |
### Making Commits
```bash
# Stage changes
git add path/to/changed/file.py
# Commit with a descriptive message
git commit -m "Add voice cloning support to the tool system
- Added speech_to_text and text_to_speech tools
- Implemented voice_clone tool for custom voice synthesis
- Added voice processing pipeline with Coqui TTS
- Updated documentation with voice examples
Closes: #123"
```
### Commit Message Format
```
<type>(<scope>): <subject>
<body>
<footer>
```
**Types:**
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation changes
- `style`: Formatting, missing semicolons, etc.
- `refactor`: Code refactoring
- `test`: Adding tests
- `chore`: Maintenance tasks
**Example:**
```
feat(tools): add file search functionality
Implemented fuzzy file search using fzf for quick file discovery.
Added search_files tool that supports:
- Pattern matching with glob
- Fuzzy search with fzf
- File type filtering
Closes: #45
```
---
## Submitting Pull Requests
### Before Submitting
1. **Run Tests:**
```bash
# Run all tests
pytest
# Run with coverage
pytest --cov=stack_cli --cov-report=html
# Run specific test file
pytest tests/test_agent.py -v
```
2. **Run Linters:**
```bash
# All linters
make lint
# Individual linters
black --check stack_cli/
flake8 stack_cli/
mypy stack_cli/
```
3. **Format Code:**
```bash
# Auto-format code
black stack_cli/
# Sort imports
isort stack_cli/
```
### Pull Request Process
1. **Create Pull Request:**
```bash
# Push your branch
git push origin feature/your-feature-name
# Open PR on GitHub or use CLI
gh pr create --title "Add feature" --body "Description"
```
2. **PR Description Template:**
```markdown
## Summary
Brief description of what this PR does.
## Changes Made
- List of specific changes
- Another change
## Motivation
Why is this change needed?
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests passed
- [ ] Manual testing completed
## Screenshots (if applicable)
## Related Issues
Closes #123
```
3. **Review Process:**
- Address review comments promptly
- Keep commits atomic and well-described
- Force push to update PR if needed (after reviewers approve)
### What We Look For
✅ Code that follows our style guidelines
✅ Tests that cover the new functionality
✅ Documentation updates (if applicable)
✅ Clear commit messages
✅ No breaking changes (or clearly documented)
✅ Performance implications considered
---
## Writing Tests
### Test Structure
```python
# tests/test_example.py
"""
Tests for the example module.
"""
import pytest
from unittest.mock import Mock, patch
from stack_cli.example import ExampleClass, process_data
class TestExampleClass:
"""Tests for ExampleClass."""
def setup_method(self):
"""Set up test fixtures."""
self.example = ExampleClass(name="test", value=42)
def test_initialization(self):
"""Test class initialization."""
assert self.example.name == "test"
assert self.example.value == 42
def test_negative_value_raises(self):
"""Test that negative values raise ValueError."""
with pytest.raises(ValueError, match="non-negative"):
ExampleClass(name="test", value=-1)
def test_process_returns_dict(self):
"""Test that process returns expected dictionary."""
result = self.example.process(["hello", "world"])
assert isinstance(result, dict)
assert result["hello"] == 5
assert result["world"] == 5
def test_process_empty_list_raises(self):
"""Test that processing empty list raises ValueError."""
with pytest.raises(ValueError, match="cannot be empty"):
self.example.process([])
class TestProcessData:
"""Tests for process_data function."""
@patch("stack_cli.example.external_service")
def test_calls_external_service(self, mock_service):
"""Test that external service is called correctly."""
mock_service.return_value = {"status": "ok"}
result = process_data(["test"])
mock_service.assert_called_once_with(["test"])
assert result["status"] == "ok"
```
### Test Categories
| Category | Location | Description |
|----------|----------|-------------|
| Unit Tests | `tests/unit/` | Test individual functions/classes |
| Integration Tests | `tests/integration/` | Test component interactions |
| API Tests | `tests/api/` | Test API endpoints |
| Tool Tests | `tests/tools/` | Test tool implementations |
| Pattern Memory Tests | `tests/self_evolution/` | Test learning system |
### Running Tests
```bash
# All tests
pytest
# Specific category
pytest tests/unit/
# With coverage
pytest --cov=stack_cli --cov-report=term-missing --cov-report=html
# Watch mode (auto-run on changes)
ptw # pytest-watch
# Specific test
pytest tests/test_example.py::TestExampleClass::test_initialization -v
```
### Test Fixtures
```python
# conftest.py
import pytest
from pathlib import Path
import tempfile
import shutil
@pytest.fixture
def temp_dir():
"""Create a temporary directory for testing."""
tmpdir = tempfile.mkdtemp()
yield Path(tmpdir)
shutil.rmtree(tmpdir)
@pytest.fixture
def sample_project(temp_dir):
"""Create a sample project structure for testing."""
project = temp_dir / "project"
project.mkdir()
# Create sample files
(project / "main.py").write_text("def main(): pass")
(project / "test.py").write_text("def test(): pass")
return project
@pytest.fixture
def mock_memory():
"""Mock memory system for isolated testing."""
from unittest.mock import MagicMock
memory = MagicMock()
memory.store_memory.return_value = 1
memory.find_similar.return_value = []
return memory
```
---
## Documentation Guidelines
### Docstring Format
We use Sphinx-style docstrings:
```python
def function_name(param1: str, param2: int, param3: Optional[List] = None) -> Dict:
"""Brief description of the function.
Longer description if needed, explaining what the function does,
its purpose, and any important details about its behavior.
Args:
param1: Description of param1.
param2: Description of param2. Must be positive.
param3: Optional description. Defaults to None.
Returns:
Description of the return value. Includes type information.
Raises:
ValueError: When param2 is negative.
TypeError: When param1 is not a string.
Example:
>>> result = function_name("hello", 42)
>>> print(result)
{'param1': 'hello', 'param2': 42}
"""
pass
```
### README Updates
When adding new features, update the README.md:
1. Add feature to the features table
2. Include example usage
3. Update architecture diagram if needed
4. Add benchmark results if applicable
### API Documentation
For API changes, update `API.md`:
```markdown
### Endpoint Name
**Endpoint:** `POST /endpoint`
**Description:** What this endpoint does.
**Request Body:**
```json
{
"field1": "description",
"field2": 123
}
```
**Response:**
```json
{
"result": "description"
}
```
```
---
## Bug Reports
### Before Submitting a Bug Report
- Search existing issues to avoid duplicates
- Try to reproduce the issue with the latest version
- Gather relevant information:
- Python version
- Stack 2.9 version
- Operating system
- Error message and stack trace
- Steps to reproduce
### Submitting a Bug Report
Use the GitHub issue tracker with the "bug" label:
```markdown
## Bug Description
Clear description of the bug.
## Steps to Reproduce
1. Go to '...'
2. Run '...'
3. See error
## Expected Behavior
What you expected to happen.
## Actual Behavior
What actually happened.
## Environment
- OS: [e.g., Ubuntu 22.04]
- Python: [e.g., 3.11.4]
- Stack 2.9: [e.g., 1.0.0]
## Stack Trace
```
Full error traceback here
```
## Additional Context
Any other relevant information.
```
---
## Feature Requests
### Before Submitting a Feature Request
- Search existing issues and PRs
- Consider if the feature aligns with project goals
- Think about implementation approaches
### Submitting a Feature Request
```markdown
## Feature Description
Clear description of the proposed feature.
## Motivation
Why is this feature needed? What problem does it solve?
## Proposed Implementation
How you envision implementing this feature.
## Alternatives Considered
Other approaches you've considered.
## Additional Context
Mockups, diagrams, or other supporting materials.
```
---
## Recognition
Contributors will be recognized in:
- The project's README acknowledgments section
- Release notes for their contributions
- Our community highlights
---
## Questions?
- **GitHub Discussions**: [Q&A Category](https://github.com/openclaw/stack-2.9/discussions)
- **Discord**: Join our community server
- **Email**: support@stack2.9.openclaw.org
---
Thank you for contributing to Stack 2.9! 🎉