- rebuild room and user metadata from synced space topology at startup
- run reconciliation before sync_forever and persist legacy platform_chat_id backfills
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.
AgentApiWrapper._build_ws_url was building /v1/agent_ws/{chat_id}/
which does not exist in platform-agent. Fixed to /agent_ws/?thread_id={chat_id}
to match the actual endpoint and query-param isolation scheme.
Also simplify Matrix MVP settings handlers to MVP_UNAVAILABLE stubs
and add handle_unknown_command for unregistered !commands.
- 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
- Drop reaction-based skill and confirmation helpers from Matrix conversion
- Render !settings as a strict read-only dashboard snapshot
- Align Matrix adapter regressions with command-only helper text
- replace reaction-based helper text with !yes/!no and !skill commands
- resolve confirm and cancel through pending confirmation state
- render !settings as a read-only status dashboard
- drop reaction event handling from Matrix bot
- render OutgoingUI as text with !yes/!no instructions
- persist pending confirmations when UI buttons are sent
- register archive and rename as client-aware closure handlers
- rename matrix rooms via stored surface_ref when a client is available
- keep archive scoped to core chat state for phase 1
- create new chat rooms inside the user's space
- store space-aware room metadata with next_chat_id
- handle room creation failures with user-facing messages
- 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