Three workstreams implemented: W1 (Repo Split): Remove proprietary BloxServer files and docs, update pyproject.toml URLs to public GitHub, clean doc references, add CI workflow (.github/workflows/ci.yml) and CONTRIBUTING.md. W2 (Message Journal): Add DispatchHook protocol for dispatch lifecycle events, SQLite-backed MessageJournal with WAL mode for certified-mail delivery guarantees (PENDING→DISPATCHED→ACKED/FAILED), integrate hooks into StreamPump._dispatch_to_handlers(), add journal REST endpoints, and aiosqlite dependency. W3 (Hot Deployment): Add RestartOrchestrator for graceful restart with queue drain and journal stats collection, SIGHUP signal handler in CLI, POST /organism/restart endpoint, restart-aware app lifespan with journal recovery on boot, and os.execv/subprocess re-exec for Unix/Windows. All 439 tests pass (37 new tests for W2/W3). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2.1 KiB
2.1 KiB
Contributing to xml-pipeline
Thank you for considering contributing to xml-pipeline.
Development Setup
git clone https://github.com/xml-pipeline/xml-pipeline.git
cd xml-pipeline
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
pip install -e ".[dev]"
Running Tests
pytest tests/ -v
Skip slow/integration tests:
pytest tests/ -v -m "not slow"
Code Style
This project uses ruff for linting and formatting, mypy for type checking.
ruff check xml_pipeline/ tests/
ruff format xml_pipeline/ tests/
mypy xml_pipeline/
All functions must have type hints. Async handlers use async def.
Pull Request Process
- Fork the repo and create a feature branch from
main. - Write tests for new functionality in
tests/. - Ensure
pytest,ruff check, andmypypass. - Keep commits focused and write clear commit messages.
- Open a PR against
mainwith a description of what changed and why.
Architecture
Read CLAUDE.md for the full architecture overview. Key principles:
- XML is the sovereign wire format -- all messages are validated XML envelopes.
- Handlers are untrusted -- the pump enforces identity, routing, and thread isolation.
- Pipeline steps are composable -- add new processing stages by inserting async functions.
- Async-first -- everything is
async def, powered by aiostream.
Adding a New Pipeline Step
- Create
xml_pipeline/message_bus/steps/your_step.py. - Implement
async def your_step(state: MessageState) -> MessageState. - Insert into the pipeline in
stream_pump.pybuild_pipeline(). - Add tests in
tests/test_pipeline_steps.py.
Adding a New Handler
- Define a
@xmlify @dataclasspayload in your handler module. - Write an
async def handle_*(payload, metadata) -> HandlerResponse | None. - Register in
organism.yamlunderlisteners. - See
docs/handler-contract-v2.1.mdfor the full contract.
License
By contributing, you agree that your contributions will be licensed under the MIT License.