Agent routing:
- Remove !agent command and manual agent selection flow
- Registry auto-assigns agent from user_agents mapping (fallback: agents[0])
- provision_workspace_chat and !new both write agent_id to room_meta
- Reconciliation backfills agent_id from registry on cold start
- Fix duplicate agent_id block in auth.py
Deployment stability:
- Add bot-state named volume to persist lambda_matrix.db and matrix_store
- Fix docker-compose.prod.yml duplicate environment: key (was silently losing all Matrix credentials)
- Fix MATRIX_AGENT_REGISTRY_PATH to use absolute container path /app/config/...
- Add bot-state volume declaration to docker-compose.fullstack.yml
Docs and config:
- Rewrite README.md for platform handoff (deploy table, working commands only)
- Rewrite docs/matrix-prototype.md (remove stale commands and mock descriptions)
- Remove !save/!load/!context/!agent from help text and welcome message
- Add !clear, !list, !remove, !yes/!no to help text
- Clean up .env.example (remove Telegram token, internal vars, real URLs)
- Update config/matrix-agents.example.yaml with user_agents section and comments
- Add explanatory comment to Dockerfile for --ignore-requires-python
- Remove silent uv sync fallbacks in Dockerfile
Task 4: stale room blocking + agent_id binding
- MatrixBot._check_agent_routing: blocks normal messages when user has no
selected agent or room is bound to a different agent
- agent_routing_enabled flag on MatrixRuntime activates the check only
in real multi-agent mode (RoutedPlatformClient)
- make_handle_new_chat now writes agent_id into new room metadata when
user already has a selected agent
Task 5: durable restart state tests
- test_restart_persistence.py proves selected_agent_id, room agent_id,
platform_chat_id, and the sequence counter all survive SQLiteStore
close/reopen; also covers clean startup with no prior state
Users can now list available agents with !agent and select one by
number. Selection persists in user metadata (selected_agent_id). If the
current room has no agent binding yet, selecting an agent binds it
immediately so the user can start messaging without !new.
Also updates the dispatcher test to reflect that real-mode platform is
now RoutedPlatformClient, not a bare RealPlatformClient.
Instead of calling a /reset endpoint on platform-agent, !reset now
generates a new thread_id (platform_chat_id) for the room. The old
WebSocket connection is closed and the next message creates a fresh
context automatically. No platform changes required.
- harden Matrix onboarding/chat lifecycle after manual QA
- refresh README and Matrix docs to match current behavior
- add local ignores for runtime artifacts and include current planning/report docs
Closes#7Closes#9Closes#14
- Seed invite tests with explicit next_chat_index progression instead of C1 assumptions
- Separate Matrix room ids from logical chat ids in dispatcher coverage
- Verify the full Matrix adapter suite against the tightened assertions
- Assert skills text no longer includes reaction-era labels
- Require converter to drop reaction callback support
- Lock !settings dashboard to read-only snapshot copy
- add MAT-01..MAT-07 and MAT-09..MAT-12 regression tests for matrix adapter
- extend store and dispatcher coverage for pending confirmations and settings dashboard
- verify matrix adapter suite and full pytest suite stay green
- rewrite invite/new-chat assertions for Space-based Matrix flow
- replace legacy reaction text checks with !skill on/off expectations
- validate confirmation text against !yes and !no prompts
- sdk/mock.py: stream_message was async def (coroutine), must be async
generator with yield — caused TypeError on every user message
- topic_events.py: on_topic_created now skips bot-created topics
(from_user.id == bot.id); cmd_new already registers them under the
correct human user_id
- commands.py: cmd_archive now sends "Чат архивирован." confirmation
- test_topic_events.py: add bot=SimpleNamespace(id=BOT_ID) to fixture