surfaces/.planning/codebase/STRUCTURE.md
Mikhail Putilovskij c9072d51ea docs: add codebase map to .planning/codebase/
7 documents covering stack, integrations, architecture, structure,
conventions, testing, and concerns.
2026-04-02 00:00:51 +03:00

210 lines
10 KiB
Markdown

# Codebase Structure
**Analysis Date:** 2026-04-01
## Directory Layout
```
surfaces-bot/
├── adapter/
│ ├── __init__.py
│ └── matrix/ # matrix-nio adapter (merged to main)
│ ├── __init__.py
│ ├── bot.py # Entry point, MatrixBot class, send_outgoing()
│ ├── converter.py # nio Event → IncomingEvent
│ ├── reactions.py # Emoji constants, skills text builder
│ ├── room_router.py # room_id → chat_id resolution
│ ├── store.py # Matrix-specific StateStore helpers (room meta, user meta)
│ └── handlers/
│ ├── __init__.py # register_matrix_handlers()
│ ├── auth.py # handle_invite (invite member event)
│ ├── chat.py # Chat creation (creates real Matrix rooms)
│ ├── confirm.py # Confirmation flow callbacks
│ └── settings.py # Settings sub-commands and toggle_skill
├── core/
│ ├── auth.py # AuthManager: start_flow, confirm, is_authenticated
│ ├── chat.py # ChatManager: get_or_create, list_active, rename, archive
│ ├── handler.py # EventDispatcher: register, dispatch, _routing_key
│ ├── protocol.py # All shared dataclasses and type aliases
│ ├── settings.py # SettingsManager: get (cached), apply (invalidates cache)
│ ├── store.py # StateStore Protocol, InMemoryStore, SQLiteStore
│ └── handlers/
│ ├── __init__.py # register_all() — binds all core handlers to dispatcher
│ ├── callback.py # handle_confirm, handle_cancel, handle_toggle_skill
│ ├── chat.py # handle_new_chat, handle_rename, handle_archive, handle_list_chats
│ ├── message.py # handle_message — auth guard + platform.send_message
│ ├── settings.py # handle_settings — displays settings menu
│ └── start.py # handle_start — get_or_create_user + welcome message
├── sdk/
│ ├── __init__.py
│ ├── interface.py # PlatformClient Protocol, WebhookReceiver Protocol, Pydantic models
│ └── mock.py # MockPlatformClient — full in-memory implementation
├── tests/
│ ├── __init__.py
│ ├── conftest.py # (root conftest — sys.path fix for local sdk/ shadowing stdlib)
│ ├── adapter/
│ │ ├── __init__.py
│ │ ├── matrix/
│ │ │ ├── __init__.py
│ │ │ ├── test_converter.py
│ │ │ ├── test_dispatcher.py
│ │ │ ├── test_reactions.py
│ │ │ └── test_store.py
│ │ └── test_forum_db.py # untracked — forum DB exploration
│ ├── core/
│ │ ├── test_auth.py
│ │ ├── test_chat.py
│ │ ├── test_dispatcher.py
│ │ ├── test_integration.py
│ │ ├── test_protocol.py
│ │ ├── test_settings.py
│ │ ├── test_store.py
│ │ └── test_voice_slot.py
│ └── platform/
│ └── test_mock.py
├── docs/ # All human documentation
├── .planning/ # GSD planning artefacts
│ └── codebase/ # Codebase map documents (this directory)
├── .claude/
│ └── agents/ # Agent configuration files
├── .worktrees/
│ └── telegram/ # Telegram adapter on feat/telegram-adapter branch
│ └── ... # Mirrors main layout; merged separately
├── conftest.py # Root pytest conftest: sys.path hack for local sdk/
├── pyproject.toml # Project metadata, dependencies, ruff + pytest config
├── uv.lock # Lockfile (uv)
├── lambda_matrix.db # SQLite DB written by Matrix bot (gitignored)
└── .env.example # Environment variable template
```
## Directory Purposes
**`core/`:**
- Purpose: Platform-neutral business logic. Never imports from `adapter/`.
- Key files: `protocol.py` (all shared types), `handler.py` (dispatcher), `store.py` (persistence interface)
- Add new domain logic here; keep it free of aiogram/matrix-nio imports
**`core/handlers/`:**
- Purpose: One async function per command/callback/message type. Each returns `list[OutgoingEvent]`.
- Registration: `register_all()` in `core/handlers/__init__.py` binds them to the dispatcher
- Adapters can override any key by calling `dispatcher.register(event_type, key, fn)` after `register_all()`
**`sdk/`:**
- Purpose: Contract (`interface.py`) and mock (`mock.py`) for the Lambda AI platform SDK
- Note: The directory is named `sdk/` in actual code (not `platform/` as CLAUDE.md describes); `handler.py` imports from `sdk.interface`
- When real SDK arrives: replace `sdk/mock.py` only; `sdk/interface.py` must not change unless the contract changes
**`adapter/matrix/`:**
- Purpose: Everything matrix-nio-specific. Translates between nio and core protocol.
- `bot.py` owns `MatrixBot`, `build_runtime()`, `send_outgoing()`, and `main()`
- `store.py` provides key-namespaced helpers on top of `StateStore` (not a separate store implementation)
- `room_router.py` maintains the `room_id → chat_id` mapping persisted in `StateStore`
**`adapter/telegram/`:**
- Purpose: aiogram 3.x adapter. Lives in `.worktrees/telegram/` on `feat/telegram-adapter` branch.
- Uses aiogram FSM states (`states.py`) and inline keyboards (`keyboards/`)
- Not yet merged to `main`
**`tests/`:**
- Purpose: pytest test suite mirroring the source tree
- `tests/core/` — unit tests for each core module
- `tests/adapter/matrix/` — Matrix adapter tests (converter, dispatcher, reactions, store)
- `tests/platform/` — MockPlatformClient tests
**`docs/`:**
- Purpose: Human-readable design documents; not consumed by code
- Key docs: `docs/surface-protocol.md` (unification rationale), `docs/api-contract.md` (SDK contract), `docs/telegram-prototype.md`, `docs/matrix-prototype.md`
## Key File Locations
**Entry Points:**
- `adapter/matrix/bot.py` — Matrix bot `main()`, run via `python -m adapter.matrix.bot`
- `.worktrees/telegram/adapter/telegram/bot.py` — Telegram bot entry (feature branch)
**Shared Protocol:**
- `core/protocol.py` — single source of truth for all inter-layer data types
**SDK Contract:**
- `sdk/interface.py``PlatformClient` Protocol; defines the API surface for the real SDK
- `sdk/mock.py``MockPlatformClient`; current runtime implementation
**Dispatcher Registration:**
- `core/handlers/__init__.py``register_all()` for platform-agnostic handlers
- `adapter/matrix/handlers/__init__.py``register_matrix_handlers()` for Matrix overrides
**Persistence:**
- `core/store.py``StateStore` Protocol, `InMemoryStore`, `SQLiteStore`
- `adapter/matrix/store.py` — Matrix-specific store helper functions (not a store implementation)
**Configuration:**
- `pyproject.toml` — dependencies, pytest config (`asyncio_mode = "auto"`, `pythonpath = ["."]`), ruff config
- `conftest.py``sys.path` insert so local `sdk/` shadows stdlib `platform` module
## Naming Conventions
**Files:**
- Modules: `snake_case.py`
- Entry points: `bot.py` per adapter
- Converter: `converter.py` per adapter
- Handlers directory: `handlers/` per layer
**Classes:**
- Managers: `{Domain}Manager` (e.g. `ChatManager`, `AuthManager`, `SettingsManager`)
- Bot runtime: `{Platform}Bot` (e.g. `MatrixBot`)
- Protocol types: PascalCase dataclasses (e.g. `IncomingMessage`, `OutgoingUI`)
- SDK types: PascalCase Pydantic models (e.g. `MessageResponse`, `UserSettings`)
**Handler functions:**
- `handle_{command}` for command handlers (e.g. `handle_start`, `handle_new_chat`)
- `make_handle_{command}` for factory functions that close over adapter state (e.g. `make_handle_new_chat(client, store)`)
**State keys:**
- `"{namespace}:{discriminator}"` — always use the prefix constants defined in `adapter/matrix/store.py`
## Where to Add New Code
**New core command handler:**
1. Add `async def handle_{cmd}(event, chat_mgr, auth_mgr, settings_mgr, platform) -> list` in `core/handlers/{category}.py`
2. Register it in `core/handlers/__init__.py:register_all()` with `dispatcher.register(IncomingCommand, "{cmd}", handle_{cmd})`
3. Write tests in `tests/core/test_dispatcher.py` or a dedicated `tests/core/test_{category}.py`
**New Matrix-specific handler (needs nio client or matrix store):**
1. Add handler in `adapter/matrix/handlers/{category}.py`
2. Register in `adapter/matrix/handlers/__init__.py:register_matrix_handlers()` — this overrides the core handler for that key
**New protocol type:**
- Add dataclass to `core/protocol.py`; update `IncomingEvent` or `OutgoingEvent` union aliases if it crosses layer boundaries
- Update `EventDispatcher._routing_key()` if it requires a new dispatch strategy
**New StateStore key namespace:**
- Add prefix constant and helper functions in `adapter/matrix/store.py` (for Matrix-specific state) or directly in the relevant manager (for core state)
**New test:**
- Unit tests for core logic: `tests/core/test_{module}.py`
- Adapter tests: `tests/adapter/matrix/test_{module}.py`
- Use `InMemoryStore` as the store; use `MockPlatformClient` as the platform client
## Special Directories
**`.worktrees/telegram/`:**
- Purpose: Git worktree for `feat/telegram-adapter` branch; full copy of the repo root
- Generated: Yes (via `git worktree add`)
- Committed: No (worktrees are local)
**`.planning/`:**
- Purpose: GSD planning artefacts — phase plans and codebase maps
- Generated: Yes (by `/gsd:` commands)
- Committed: Yes (tracked with the repo)
**`.claude/agents/`:**
- Purpose: Agent role configuration files for the multi-agent workflow
- Committed: Yes
**`src/`:**
- Purpose: Contains only `surfaces_bot.egg-info/` (setuptools build artefact); no source code
- Generated: Yes
- Committed: No
---
*Structure analysis: 2026-04-01*