diff --git a/docs/v2-architecture-draft.md b/docs/v2-architecture-draft.md index 18053c7..0be4149 100644 --- a/docs/v2-architecture-draft.md +++ b/docs/v2-architecture-draft.md @@ -506,6 +506,25 @@ Two tiers: The architecture is **flexible for code changes, not configurable for everything**. Advanced setups (like the PR Factory below) use custom routing logic and host-side hooks — not database config columns. +### Code Structure for Skill Customization + +NanoClaw is customized via skills — branches that get merged into the user's installation. Different skills add different capabilities (channels, integrations, behaviors). The code must be structured so that: + +1. **Different customizations don't conflict.** Adding Slack and adding Telegram should not produce merge conflicts. Adding a new MCP tool should not conflict with adding a channel. Each type of customization should touch its own file(s). + +2. **Core blocks of functionality are in separate files.** Channel registration, message formatting, MCP tools, routing logic, container management — each in its own file. A skill that changes how messages are formatted doesn't touch the file that handles container spawning. + +3. **The index file is thin.** It wires things together (init DB, start adapters, start poll loops) but contains no business logic. All logic lives in purpose-specific modules that skills can modify independently. + +4. **Don't over-split.** A simple change (e.g., adding a new message kind) shouldn't require edits across 5 files. Group related logic together. The goal is that each skill touches 1-2 files for its core change. + +5. **Registration patterns over switch statements.** Channels, MCP tools, and providers should use registration/plugin patterns. A skill adds a channel by adding a file and a registration call — not by editing a central switch statement alongside every other channel. + +**Practical example:** Adding a new channel via skill should require: +- One new file (the channel adapter or Chat SDK config) +- One line in index or a self-registering import +- Zero changes to routing, formatting, delivery, or container code + ### What the base architecture must support primitively These are the building blocks. None require special abstractions — they fall out of per-session DBs, host-managed routing, and messages_out with `kind: 'system'`: