File size: 14,995 Bytes
b6ae7b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2088481
b6ae7b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
# 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! πŸŽ‰