- 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 #7 Closes #9 Closes #14
13 KiB
| phase | verified | status | score | re_verification | human_verification | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-matrix-qa-polish | 2026-04-03T09:39:38Z | human_needed | 24/24 must-haves verified |
|
|
Phase 1: Matrix QA & Polish Verification Report
Phase Goal: Переработать Matrix адаптер с DM-first на Space+rooms, убрать реакции в пользу !yes/!no, довести до уровня "приемлемо работает" как Telegram. Verified: 2026-04-03T09:39:38Z Status: human_needed Re-verification: Yes — after gap closure
Goal Achievement
Observable Truths
| # | Truth | Status | Evidence |
|---|---|---|---|
| 1 | Bot creates a Space on first invite | ✓ VERIFIED | handle_invite creates a private Space with space=True in adapter/matrix/handlers/auth.py:37. |
| 2 | Bot creates first chat room inside that Space | ✓ VERIFIED | handle_invite creates Чат 1, links it via m.space.child, and stores room metadata in adapter/matrix/handlers/auth.py:51. |
| 3 | Bot invites user to both Space and chat room | ✓ VERIFIED | client.room_invite(space_id, ...) and client.room_invite(chat_room_id, ...) in adapter/matrix/handlers/auth.py:72. |
| 4 | space_id is stored in user_meta |
✓ VERIFIED | user_meta["space_id"] = space_id in adapter/matrix/handlers/auth.py:77. |
| 5 | Repeated invite is idempotent | ✓ VERIFIED | Existing user_meta.space_id short-circuits invite flow in adapter/matrix/handlers/auth.py:22; covered by tests/adapter/matrix/test_invite_space.py:54. |
| 6 | Initial chat id comes from next_chat_id |
✓ VERIFIED | chat_id = await next_chat_id(...) in adapter/matrix/handlers/auth.py:75; dynamic progression asserted in tests/adapter/matrix/test_invite_space.py:66. |
| 7 | !new creates a room and links it into the user's Space |
✓ VERIFIED | make_handle_new_chat calls room_create, room_put_state, and room_invite in adapter/matrix/handlers/chat.py; covered by tests/adapter/matrix/test_chat_space.py:25. |
| 8 | !new without space_id returns a user-facing error |
✓ VERIFIED | Handler returns "Ошибка: Space не найден..." in adapter/matrix/handlers/chat.py:39; covered by tests/adapter/matrix/test_chat_space.py:52. |
| 9 | !archive archives chat state without Space-child removal |
✓ VERIFIED | make_handle_archive delegates only to chat_mgr.archive in adapter/matrix/handlers/chat.py:119; covered by tests/adapter/matrix/test_chat_space.py:76. |
| 10 | !rename updates Matrix room name when client is available |
✓ VERIFIED | client.room_set_name(ctx.surface_ref, new_name) in adapter/matrix/handlers/chat.py:106. |
| 11 | RoomCreateError from !new is handled gracefully |
✓ VERIFIED | User-facing "Не удалось создать комнату." in adapter/matrix/handlers/chat.py:66; covered by tests/adapter/matrix/test_chat_space.py:97. |
| 12 | Outgoing UI sends plain text with !yes / !no, no reactions |
✓ VERIFIED | send_outgoing emits only m.room.message and appends the command hint in adapter/matrix/bot.py:140; covered by tests/adapter/matrix/test_send_outgoing.py:18. |
| 13 | _button_action_to_reaction is removed |
✓ VERIFIED | No such symbol exists in adapter/matrix/bot.py; reaction path is absent. |
| 14 | on_reaction callback is removed |
✓ VERIFIED | MatrixBot registers only message and member callbacks in adapter/matrix/bot.py:200. |
| 15 | ReactionEvent import is removed |
✓ VERIFIED | adapter/matrix/bot.py imports no reaction event types. |
| 16 | build_skills_text no longer mentions reactions 1-9 |
✓ VERIFIED | build_skills_text renders only command help in adapter/matrix/reactions.py:6; enforced by tests/adapter/matrix/test_reactions.py:10. |
| 17 | build_confirmation_text uses !yes/!no |
✓ VERIFIED | build_confirmation_text returns the command-only prompt in adapter/matrix/reactions.py:16. |
| 18 | !yes resolves pending confirmation |
✓ VERIFIED | make_handle_confirm reads (event.user_id, payload.room_id) in adapter/matrix/handlers/confirm.py:14; adapter round-trip covered by tests/adapter/matrix/test_send_outgoing.py:63 and a fresh inline spot-check returned Подтверждено: Archive room. |
| 19 | !no clears pending confirmation |
✓ VERIFIED | make_handle_cancel clears the same scoped key in adapter/matrix/handlers/confirm.py:41; covered by tests/adapter/matrix/test_send_outgoing.py:112 and a fresh inline spot-check returned Действие отменено. |
| 20 | !settings is a read-only dashboard |
✓ VERIFIED | Dashboard output in adapter/matrix/handlers/settings.py:48 contains snapshot sections only; tests/adapter/matrix/test_dispatcher.py:161 and a fresh spot-check confirm Изменить is absent. |
| 21 | Previously broken Matrix tests are green | ✓ VERIFIED | pytest tests/adapter/matrix/ -q passed with 39 passed in 0.75s. |
| 22 | MAT-01..MAT-12 tests exist and are green | ✓ VERIFIED | Dedicated invite/chat/send_outgoing/confirm coverage exists in tests/adapter/matrix/ and passed in the Matrix suite. |
| 23 | Full test suite exceeds 96 passing tests | ✓ VERIFIED | pytest tests/ -q passed with 112 passed in 3.48s. |
| 24 | No Matrix tests rely on hardcoded legacy C1 assumptions from the old DM flow |
✓ VERIFIED | Room-aware regressions now assert dynamic chat allocation and room-id separation in tests/adapter/matrix/test_invite_space.py:66, tests/adapter/matrix/test_dispatcher.py:54, and tests/adapter/matrix/test_send_outgoing.py:63. Remaining C1 literals are generic sample chat ids, not DM-flow assumptions. |
Score: 24/24 truths verified
Required Artifacts
| Artifact | Expected | Status | Details |
|---|---|---|---|
adapter/matrix/store.py |
pending-confirm helpers and metadata helpers | ✓ VERIFIED | Composite pending-confirm keys exist and are used by bot and confirm handlers. |
adapter/matrix/handlers/auth.py |
Space+rooms invite flow | ✓ VERIFIED | Creates Space, links Чат 1, stores metadata, invites the user, and sends welcome text. |
adapter/matrix/room_router.py |
room-aware chat resolution without auto-registration | ✓ VERIFIED | Returns stored chat_id or explicit unregistered:{room_id} fallback. |
adapter/matrix/handlers/chat.py |
Space-aware !new, !archive, !rename |
✓ VERIFIED | Wired via handler registration and covered by chat-space tests. |
adapter/matrix/bot.py |
reaction-free send path and pending-confirm persistence | ✓ VERIFIED | OutgoingUI persists confirmations under (matrix_user_id, room_id) before !yes/!no resolution. |
adapter/matrix/converter.py |
command-only Matrix callback conversion | ✓ VERIFIED | !yes and !no carry room_id; no from_reaction export remains. |
adapter/matrix/reactions.py |
command-only helper text | ✓ VERIFIED | Skill and confirmation text mention commands, not reactions. |
adapter/matrix/handlers/confirm.py |
!yes/!no handlers using pending confirmations |
✓ VERIFIED | Runtime and legacy fallback paths both behave correctly. |
adapter/matrix/handlers/settings.py |
read-only !settings dashboard |
✓ VERIFIED | Snapshot-only dashboard is wired and tested. |
tests/adapter/matrix/test_invite_space.py |
invite-flow regression coverage | ✓ VERIFIED | Covers Space creation, idempotency, and non-hardcoded chat allocation. |
tests/adapter/matrix/test_chat_space.py |
Space-aware chat command coverage | ✓ VERIFIED | Covers !new, missing space_id, archive, and RoomCreateError. |
tests/adapter/matrix/test_send_outgoing.py |
outgoing UI and confirm round-trip coverage | ✓ VERIFIED | Covers send path, no reactions, and scoped confirm/cancel round trips. |
tests/adapter/matrix/test_confirm.py |
confirm handler coverage | ✓ VERIFIED | Covers scoped confirmation, cancel, no-pending behavior, and legacy fallback. |
Key Link Verification
| From | To | Via | Status | Details |
|---|---|---|---|---|
adapter/matrix/handlers/auth.py |
adapter/matrix/store.py |
set_user_meta(...space_id...) |
✓ WIRED | space_id is persisted immediately after invite flow. |
adapter/matrix/handlers/auth.py |
adapter/matrix/store.py |
next_chat_id |
✓ WIRED | Initial chat ids are allocated dynamically, not hardcoded. |
adapter/matrix/handlers/chat.py |
adapter/matrix/store.py |
get_user_meta for space_id |
✓ WIRED | !new refuses to proceed without stored Space metadata. |
adapter/matrix/handlers/chat.py |
Matrix API | m.space.child |
✓ WIRED | New rooms are linked into the user Space with room_put_state. |
adapter/matrix/bot.py |
adapter/matrix/store.py |
set_pending_confirm(store, matrix_user_id, room_id, ...) |
✓ WIRED | Confirm state is stored under runtime Matrix identity. |
adapter/matrix/handlers/confirm.py |
adapter/matrix/store.py |
get_pending_confirm / clear_pending_confirm |
✓ WIRED | Confirm handlers resolve and clear the same scoped key as the sender path. |
adapter/matrix/converter.py |
adapter/matrix/handlers/confirm.py |
callback payload carries room_id |
✓ WIRED | !yes/!no callbacks preserve room context across dispatch. |
Data-Flow Trace (Level 4)
| Artifact | Data Variable | Source | Produces Real Data | Status |
|---|---|---|---|---|
adapter/matrix/handlers/auth.py |
space_id, chat_id |
client.room_create(...), next_chat_id(...) |
Yes | ✓ FLOWING |
adapter/matrix/handlers/chat.py |
space_id |
get_user_meta(store, event.user_id) |
Yes | ✓ FLOWING |
adapter/matrix/bot.py + adapter/matrix/handlers/confirm.py |
pending confirmation | set_pending_confirm(store, matrix_user_id, room_id, ...) -> get_pending_confirm(store, event.user_id, room_id) |
Yes | ✓ FLOWING |
adapter/matrix/handlers/settings.py |
dashboard sections | settings_mgr.get(...), chat_mgr.list_active(...) |
Yes | ✓ FLOWING |
Behavioral Spot-Checks
| Behavior | Command | Result | Status |
|---|---|---|---|
| Matrix-only tests | pytest tests/adapter/matrix/ -q |
39 passed in 0.75s |
✓ PASS |
| Full test suite | pytest tests/ -q |
112 passed in 3.48s |
✓ PASS |
Real send_outgoing -> !yes path |
inline Python spot-check | Returned Подтверждено: Archive room; pending entry cleared |
✓ PASS |
Real send_outgoing -> !no path |
inline Python spot-check | Returned Действие отменено.; pending entry cleared |
✓ PASS |
!settings output |
inline Python spot-check | Snapshot dashboard rendered; Изменить absent |
✓ PASS |
Requirements Coverage
| Requirement | Source Plan | Description | Status | Evidence |
|---|---|---|---|---|
| none | 01-01..01-06 | No explicit requirements: IDs declared in phase plans or roadmap |
✓ N/A | Verification performed against previous must-haves, locked decisions from 01-CONTEXT.md, and current codebase behavior. |
Anti-Patterns Found
| File | Line | Pattern | Severity | Impact |
|---|---|---|---|---|
| none | - | No blocker or warning-level stub patterns detected in the phase artifacts re-checked for gap closure. | ℹ️ Info | Remaining C1 literals are benign sample values in tests, not evidence of DM-first wiring. |
Human Verification Required
1. Matrix Client Space UX
Test: Invite the bot from a real Matrix account, accept the Space and room invites, run !new, then exercise a confirmation flow that requires !yes and !no.
Expected: The Space should appear in the client sidebar, new rooms should appear as Space children, and confirmations should resolve cleanly without falling back to Нет ожидающих подтверждений.
Why human: Repository checks cannot validate Element or other Matrix-client rendering, invite visibility, or perceived UX quality.
Gaps Summary
Automated re-verification closed all four previously reported gaps. Phase 01 now satisfies the code-level must-haves and locked decisions: Space+rooms invite flow is wired, reaction UX is removed, !yes/!no works end-to-end on scoped pending state, !settings is snapshot-only, and the full test suite is green at 112 tests. The only remaining work is manual client-side verification of Matrix UX.
Verified: 2026-04-03T09:39:38Z Verifier: Claude (gsd-verifier)