- Extract effects as fully decoupled plugins in engine/effects/ - Add EffectConfig, EffectContext dataclasses and EffectPlugin protocol - Add EffectRegistry for plugin discovery and management - Add EffectChain for ordered pipeline execution - Move built-in effects to effects_plugins/ directory - Add interactive effects config picker during startup - Add NTFY command handler for /effects commands - Add tests for effects system (24 new tests) - Update AGENTS.md with effects plugin documentation - Add conventional commits section to AGENTS.md chore: add coverage.xml to .gitignore
186 lines
4.7 KiB
Markdown
186 lines
4.7 KiB
Markdown
# Agent Development Guide
|
|
|
|
## Development Environment
|
|
|
|
This project uses:
|
|
- **mise** (mise.jdx.dev) - tool version manager and task runner
|
|
- **hk** (hk.jdx.dev) - git hook manager
|
|
- **uv** - fast Python package installer
|
|
- **ruff** - linter and formatter
|
|
- **pytest** - test runner
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
# Install dependencies
|
|
mise run install
|
|
|
|
# Or equivalently:
|
|
uv sync
|
|
```
|
|
|
|
### Available Commands
|
|
|
|
```bash
|
|
mise run test # Run tests
|
|
mise run test-v # Run tests verbose
|
|
mise run test-cov # Run tests with coverage report
|
|
mise run lint # Run ruff linter
|
|
mise run lint-fix # Run ruff with auto-fix
|
|
mise run format # Run ruff formatter
|
|
mise run ci # Full CI pipeline (sync + test + coverage)
|
|
```
|
|
|
|
## Git Hooks
|
|
|
|
**At the start of every agent session**, verify hooks are installed:
|
|
|
|
```bash
|
|
ls -la .git/hooks/pre-commit
|
|
```
|
|
|
|
If hooks are not installed, install them with:
|
|
|
|
```bash
|
|
hk init --mise
|
|
mise run pre-commit
|
|
```
|
|
|
|
The project uses hk configured in `hk.pkl`:
|
|
- **pre-commit**: runs ruff-format and ruff (with auto-fix)
|
|
- **pre-push**: runs ruff check
|
|
|
|
## Workflow Rules
|
|
|
|
### Before Committing
|
|
|
|
1. **Always run the test suite** - never commit code that fails tests:
|
|
```bash
|
|
mise run test
|
|
```
|
|
|
|
2. **Always run the linter**:
|
|
```bash
|
|
mise run lint
|
|
```
|
|
|
|
3. **Fix any lint errors** before committing (or let the pre-commit hook handle it).
|
|
|
|
4. **Review your changes** using `git diff` to understand what will be committed.
|
|
|
|
### On Failing Tests
|
|
|
|
When tests fail, **determine whether it's an out-of-date test or a correctly failing test**:
|
|
|
|
- **Out-of-date test**: The test was written for old behavior that has legitimately changed. Update the test to match the new expected behavior.
|
|
|
|
- **Correctly failing test**: The test correctly identifies a broken contract. Fix the implementation, not the test.
|
|
|
|
**Never** modify a test to make it pass without understanding why it failed.
|
|
|
|
### Code Review
|
|
|
|
Before committing significant changes:
|
|
- Run `git diff` to review all changes
|
|
- Ensure new code follows existing patterns in the codebase
|
|
- Check that type hints are added for new functions
|
|
- Verify that tests exist for new functionality
|
|
|
|
## Testing
|
|
|
|
Tests live in `tests/` and follow the pattern `test_*.py`.
|
|
|
|
Run all tests:
|
|
```bash
|
|
mise run test
|
|
```
|
|
|
|
Run with coverage:
|
|
```bash
|
|
mise run test-cov
|
|
```
|
|
|
|
The project uses pytest with strict marker enforcement. Test configuration is in `pyproject.toml` under `[tool.pytest.ini_options]`.
|
|
|
|
## Architecture Notes
|
|
|
|
- **ntfy.py** and **mic.py** are standalone modules with zero internal dependencies
|
|
- **eventbus.py** provides thread-safe event publishing for decoupled communication
|
|
- **controller.py** coordinates ntfy/mic monitoring
|
|
- The render pipeline: fetch → render → effects → scroll → terminal output
|
|
|
|
## Effects Plugin System
|
|
|
|
The effects system is implemented as a plugin architecture in `engine/effects/`.
|
|
|
|
### Core Components
|
|
|
|
| Module | Purpose |
|
|
|--------|---------|
|
|
| `effects/types.py` | `EffectConfig`, `EffectContext` dataclasses and `EffectPlugin` protocol |
|
|
| `effects/registry.py` | Plugin discovery and management (`EffectRegistry`) |
|
|
| `effects/chain.py` | Ordered pipeline execution (`EffectChain`) |
|
|
| `effects_plugins/*.py` | Externalized effect plugins |
|
|
|
|
### Creating a New Effect
|
|
|
|
Create a file in `effects_plugins/` with a class ending in `Effect`:
|
|
|
|
```python
|
|
from engine.effects.types import EffectConfig, EffectContext
|
|
|
|
class MyEffect:
|
|
name = "myeffect"
|
|
config = EffectConfig(enabled=True, intensity=1.0)
|
|
|
|
def process(self, buf: list[str], ctx: EffectContext) -> list[str]:
|
|
# Process buffer and return modified buffer
|
|
return buf
|
|
|
|
def configure(self, config: EffectConfig) -> None:
|
|
self.config = config
|
|
```
|
|
|
|
### NTFY Commands
|
|
|
|
Send messages to the ntfy topic to control effects:
|
|
|
|
```
|
|
/effects list
|
|
/effects noise on
|
|
/effects noise off
|
|
/effects noise intensity 0.5
|
|
/effects reorder noise,glitch,fade,firehose
|
|
```
|
|
|
|
## Conventional Commits
|
|
|
|
Commit messages follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
|
|
|
```
|
|
<type>(<scope>): <description>
|
|
|
|
[optional body]
|
|
|
|
[optional footer(s)]
|
|
```
|
|
|
|
### Types
|
|
|
|
- `feat`: A new feature
|
|
- `fix`: A bug fix
|
|
- `docs`: Documentation only changes
|
|
- `style`: Changes that don't affect code meaning (formatting)
|
|
- `refactor`: Code change that neither fixes a bug nor adds a feature
|
|
- `test`: Adding or updating tests
|
|
- `chore`: Changes to build process, dependencies, etc.
|
|
|
|
### Examples
|
|
|
|
```
|
|
feat(effects): add plugin architecture for visual effects
|
|
fix(layers): resolve glitch effect not applying on empty buffer
|
|
docs(AGENTS.md): add effects plugin system documentation
|
|
test(effects): add tests for EffectChain pipeline ordering
|
|
```
|