surfaces/.planning/phases/01-matrix-qa-polish/01-VERIFICATION.md
Mikhail Putilovskij 6ced154124 feat(matrix): land QA follow-ups and refresh docs
- 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
2026-04-05 19:08:58 +03:00

13 KiB
Raw Blame History

phase verified status score re_verification human_verification
01-matrix-qa-polish 2026-04-03T09:39:38Z human_needed 24/24 must-haves verified
previous_status previous_score gaps_closed gaps_remaining regressions
gaps_found 19/24
!yes reads pending_confirm from store and returns action description
build_skills_text no longer mentions reactions 1-9
!settings returns a read-only dashboard with skills/soul/safety/chats status
No Matrix tests rely on hardcoded legacy C1 assumptions from the old DM flow
test expected why_human
Matrix client Space UX First invite creates a visible Space with Chat 1, !new creates a child room under that Space, and !archive / !yes / !no feel correct in a real Matrix client. Element or another Matrix client must render Space membership, room hierarchy, and invite UX; this cannot be proven from repository-only checks.

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.
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)