Contributions are welcome. This guide covers everything from forking the repository to passing the pre-PR checklist.
Prerequisites
- Docker 20.10+ and Docker Compose 2.0+
- Python 3.12.3
- Flutter 3.38.0+ (Dart SDK ≥3.10.8)
- Git
Setting up your development environment
Fork and clone
Fork the repository on GitHub, then clone your fork:git clone https://github.com/YOUR_USERNAME/soft-architect-ai.git
cd soft-architect-ai
Create a Python virtual environment
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r src/server/requirements.txt
Install Flutter dependencies
cd src/client && flutter pub get
cd ../../tests && flutter pub get
Configure environment variables
cp .env.example .env
# Edit .env — choose LLM_PROVIDER=local or LLM_PROVIDER=cloud
Start the Docker stack
scripts/devops/start_stack.sh
# API: http://localhost:8000
# API docs: http://localhost:8000/docs
# ChromaDB: http://localhost:8001
# Ollama: http://localhost:11434
Set up pre-commit hooks
chmod +x .git/hooks/pre-commit
# Or use the pre-commit framework:
pip install pre-commit && pre-commit install
Gitflow branching model
The project follows Gitflow strictly. Never commit directly to main or develop.
| Branch | Purpose |
|---|
main | Production-ready releases only |
develop | Integration branch for completed features |
feature/* | New features and non-emergency changes |
fix/* | Bug fixes |
security/* | Security patches |
# Create a feature branch from develop
git checkout develop
git pull origin develop
git checkout -b feature/my-feature
# When ready, open a PR targeting develop
git push origin feature/my-feature
Development workflow
Follow this sequence for every change:
Write code and tests
Follow TDD for business logic. Write a failing test first, then implement the minimum code to pass it.# Run tests as you work
scripts/testing/run_tests.sh python
scripts/testing/run_tests.sh flutter
Format your code
# Python
black src/server/ --line-length 100
ruff check --fix src/server/
# Dart
dart format src/client/
Run type checking
# Python
python -m pyright src/server/services src/server/core
# Dart
dart analyze src/client/
Run the full validation suite
./scripts/testing/PRE_PUSH_VALIDATION_MASTER.sh
This script must exit with code 0 before you push. It takes approximately 4–5 minutes.Commit with a conventional message
git add -A
git commit -m "feat: add RAG chunk size configuration endpoint"
Valid prefixes: feat:, fix:, docs:, style:, security:Push and open a PR
git push origin feature/my-feature
Open a pull request targeting the develop branch. GitHub Actions will run the CI pipeline automatically.
Code style rules
Python
- Formatter: Black, line length 100
- Linter: Ruff with rule sets
E, W, F, I, C90, N, UP, B, S
- Types: Pyright strict mode — every function must have a return type annotation
- Hashing: SHA-256 only. Never MD5 or SHA-1.
- Imports: Typed imports only. Annotate external library types explicitly.
# ✅ Correct: annotated return type
def query(self, text: str) -> dict[str, Any]:
...
# ✅ Correct: SHA-256 for IDs
hashlib.sha256(raw_id.encode("utf-8")).hexdigest()
# ❌ Wrong: missing return type annotation
def query(self, text: str):
...
# ❌ Wrong: MD5 (flagged by Ruff S324)
hashlib.md5(raw_id.encode("utf-8")).hexdigest()
Dart / Flutter
- Linter:
flutter_lints (strict rules in analysis_options.yaml)
- Color opacity: Always use
withValues(alpha: x.x), never the deprecated withOpacity()
- Error handling: Use
Either<Failure, Success> for all domain-layer error propagation
- Code generation: Run
dart run build_runner build after modifying annotated files
// ✅ Correct: withValues(alpha:)
color.withValues(alpha: 0.5)
// ❌ Wrong: withOpacity() is deprecated
color.withOpacity(0.5)
// ✅ Correct: Either for error handling
Future<Either<Failure, ArchitectureModel>> getRecommendation(
String projectId,
) async {
try {
final result = await _repository.fetch(projectId);
return Right(result);
} on NetworkFailure catch (e) {
return Left(e);
}
}
Security rules (both languages)
These rules are non-negotiable. Violations will fail code review and CI.
- Never expose stack traces to users. Log internally; return controlled error responses.
- Never hardcode credentials. Use
.env files and runtime injection only.
- Never commit
.env files. They are listed in .gitignore.
- Define custom exceptions in the domain layer and re-raise them from service layers.
# ❌ Wrong: exposes internals to the user
except Exception as e:
return {"error": str(e)}
# ✅ Correct: controlled error response
except DatabaseReadError as e:
logger.error(f"Query failed: {e.reason}", extra={"error_code": e.code})
return {"error": e.to_dict()}
Pre-PR checklist
Copy this checklist into your pull request description before requesting a review:
### Code quality
- [ ] Black formatted: `black --check src/server/`
- [ ] Ruff clean: `ruff check src/server/`
- [ ] Pyright 0 errors: `pyright src/server/services`
- [ ] Tests pass: `pytest tests/ --cov-fail-under=80 -q`
### Security and cryptography
- [ ] No MD5 or SHA-1 usage
- [ ] No sensitive data in logs
- [ ] No hardcoded credentials or secrets
- [ ] Custom exceptions used for error handling
### Type safety
- [ ] All functions have return type annotations
- [ ] All Optional values checked explicitly
- [ ] No broad `Exception` catches (use specific types)
### Testing
- [ ] Unit tests written for all new business logic
- [ ] Edge cases covered (empty inputs, None, error paths)
- [ ] External dependencies mocked in unit tests
- [ ] Coverage ≥80% verified locally
### Documentation
- [ ] Docstrings added to all public functions
- [ ] Architecture decisions documented in code comments
- [ ] New doc pages added to both `doc/English/` and `doc/Español/`
### Git hygiene
- [ ] `PRE_PUSH_VALIDATION_MASTER.sh` passed (exit 0)
- [ ] Commit messages follow `feat:|fix:|docs:|style:|security:` convention
- [ ] No `.env` files committed
- [ ] No hardcoded paths or credentials in source code
Documentation standards
All project documentation lives in doc/ and follows a bilingual mirror structure:
doc/
├── English/ # English documentation
└── Español/ # Spanish documentation (identical structure)
Every document added to doc/English/ must have a corresponding translation in doc/Español/ with the same filename and directory path. The language is determined by the parent directory, not by a file extension.
File naming rules:
- Use
UPPERCASE_SNAKE_CASE for document filenames
- Never use
.en.md or .es.md extensions (these are the old system)
- Place files in the correct category subfolder (
01-PROJECT_REPORT/, 02-SETUP_DEV/, etc.)
Run the sync script after adding documents to keep the mirror consistent:
python3 doc/scripts/sync_mirror_bilingual.py
# Verify both directories have the same structure
diff -r doc/English/ doc/Español/ --brief | grep -v "Binary"
License
SoftArchitect AI is released under the GPL-3.0 license. By contributing, you agree that your contributions will be licensed under GPL-3.0.