forked from genewildish/Mainline
- Cherry-pick C&C support (ntfy poller for commands, response handling) - Compact mise.toml with native dependency chaining - Update AGENTS.md with C&C documentation - Update README.md with display modes and C&C usage
143 lines
4.2 KiB
Markdown
143 lines
4.2 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 --all-extras # includes mic support
|
|
```
|
|
|
|
### 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 test-browser # Run e2e browser tests (requires playwright)
|
|
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 (topics-init + lint + test-cov)
|
|
```
|
|
|
|
### Runtime Commands
|
|
|
|
```bash
|
|
mise run run # Run mainline (terminal)
|
|
mise run run-poetry # Run with poetry feed
|
|
mise run run-firehose # Run in firehose mode
|
|
mise run run-websocket # Run with WebSocket display only
|
|
mise run run-both # Run with both terminal and WebSocket
|
|
mise run run-client # Run both + open browser
|
|
mise run cmd # Run C&C command interface
|
|
```
|
|
|
|
## 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 and event publishing
|
|
- **effects/** - plugin architecture with performance monitoring
|
|
- The render pipeline: fetch → render → effects → scroll → terminal output
|
|
|
|
### Display System
|
|
|
|
- **Display abstraction** (`engine/display.py`): swap display backends via the Display protocol
|
|
- `TerminalDisplay` - ANSI terminal output
|
|
- `WebSocketDisplay` - broadcasts to web clients via WebSocket
|
|
- `MultiDisplay` - forwards to multiple displays simultaneously
|
|
|
|
- **WebSocket display** (`engine/websocket_display.py`): real-time frame broadcasting to web browsers
|
|
- WebSocket server on port 8765
|
|
- HTTP server on port 8766 (serves HTML client)
|
|
- Client at `client/index.html` with ANSI color parsing and fullscreen support
|
|
|
|
### Command & Control
|
|
|
|
- C&C uses separate ntfy topics for commands and responses
|
|
- `NTFY_CC_CMD_TOPIC` - commands from cmdline.py
|
|
- `NTFY_CC_RESP_TOPIC` - responses back to cmdline.py
|
|
- Effects controller handles `/effects` commands (list, on/off, intensity, reorder, stats) |