7.7 KiB
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01.1-matrix-restart-reconciliation-and-dev-reset-workflow | 01 | execute | 1 |
|
true |
|
Purpose: Per D-01 through D-07, the adapter must stop treating local SQLite state as the only truth in dev. Startup and recovery code need a single helper module that can rebuild local metadata from the homeserver room graph without creating duplicate Spaces or chats.
Output: adapter/matrix/reconcile.py with full-run and single-room recovery helpers, plus targeted pytest coverage.
<execution_context> @/Users/a/.codex/get-shit-done/workflows/execute-plan.md @/Users/a/.codex/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md @.planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-RESEARCH.md @.planning/phases/01-matrix-qa-polish/01-01-SUMMARY.md @adapter/matrix/store.py @adapter/matrix/handlers/auth.py @core/chat.py @tests/adapter/matrix/test_invite_space.py From `adapter/matrix/store.py`:async def get_room_meta(store: StateStore, room_id: str) -> dict | None
async def set_room_meta(store: StateStore, room_id: str, meta: dict) -> None
async def get_user_meta(store: StateStore, matrix_user_id: str) -> dict | None
async def set_user_meta(store: StateStore, matrix_user_id: str, meta: dict) -> None
From core/chat.py:
async def get_or_create(
self,
user_id: str,
chat_id: str,
platform: str,
surface_ref: str,
name: str | None = None,
) -> ChatContext
From Phase 01 room metadata shape:
{
"room_type": "chat",
"chat_id": "C4",
"display_name": "Чат 4",
"matrix_user_id": "@alice:example.org",
"space_id": "!space:example.org",
}
Task 1: Add reconciliation module for startup and single-room recovery
adapter/matrix/reconcile.py, tests/adapter/matrix/test_reconcile.py
adapter/matrix/store.py, adapter/matrix/handlers/auth.py, core/chat.py, tests/adapter/matrix/test_invite_space.py, .planning/phases/01.1-matrix-restart-reconciliation-and-dev-reset-workflow/01.1-CONTEXT.md
- Test 1: `reconcile_matrix_state(...)` recreates missing `matrix_user:*`, `matrix_room:*`, and `chat:*` entries from joined Matrix rooms without calling `room_create`.
- Test 2: `reconcile_matrix_state(...)` leaves already-correct local metadata intact and reports restored vs skipped/conflicting rooms.
- Test 3: `reconcile_single_room(...)` can repair one `unregistered:{room_id}` chat room on demand and recompute `next_chat_index` for that user.
- Test 4: Space rooms or unrelated joined rooms are skipped, not converted into chat rows.
Create `adapter/matrix/reconcile.py` as the authoritative recovery module for this phase. Implement a small, explicit API that Plan 02 can wire directly:
async def reconcile_matrix_state(client: Any, store: StateStore, chat_mgr: ChatManager) -> dict: ...
async def reconcile_single_room(
client: Any, store: StateStore, chat_mgr: ChatManager, room_id: str, matrix_user_id: str
) -> dict: ...
Inside this module, add focused private helpers as needed for room classification, extracting room names, parsing C<number> ids, and recomputing next_chat_index. Keep the logic non-destructive per D-04:
- never call
room_create,room_invite, or provisioning code fromhandlers/auth.py - prefer already-hydrated room data from the post-sync client object, and only fall back to explicit room-state fetches if required for room classification
- rebuild only the minimal metadata required by D-03:
matrix_user:*,matrix_room:*, and missingchat:{user}:{chat_id}records - if
chat:*exists but points at the wrongsurface_ref, repair it from Matrix room metadata and include the fix in the returned report - derive
next_chat_indexfrom the highest recoveredC<number>for that user instead of trusting stale local counters
Return a structured reconciliation report with stable keys such as:
joined_rooms, restored_user_meta, restored_room_meta, restored_chat_rows, repaired_chat_rows, skipped_rooms, and conflicts.
Write tests/adapter/matrix/test_reconcile.py with lightweight SimpleNamespace/fake-client fixtures following the existing Matrix test style. Cover both full startup reconciliation and reconcile_single_room(...). Assert that no provisioning calls are made during reconciliation, because D-04 forbids creating new Space/room topology while recovering local state.
cd /Users/a/MAI/sem2/lambda/surfaces-bot && pytest tests/adapter/matrix/test_reconcile.py -q
<acceptance_criteria>
adapter/matrix/reconcile.pyexportsreconcile_matrix_stateandreconcile_single_room.- Reconciliation restores missing
matrix_user:*,matrix_room:*, andchat:*entries for already-joined Matrix chat rooms per D-02 and D-03. - Reconciliation does not call
room_createor otherwise provision new server-side rooms per D-04. - The report returned by reconciliation clearly distinguishes restored items, skipped rooms, and conflicts.
tests/adapter/matrix/test_reconcile.pyprovesnext_chat_indexis recomputed from recovered chat ids rather than stale local state. </acceptance_criteria> The repository has an executable, tested reconciliation layer that can rebuild local Matrix metadata after dev-state loss without duplicating server-side rooms.
<success_criteria>
- Matrix recovery logic exists as a dedicated module instead of being scattered through handlers.
- Reconciliation is idempotent, non-destructive, and sufficient to restore routing/chat metadata from existing Matrix rooms.
- Plan 02 can wire startup and first-access recovery by calling exported functions rather than inventing new recovery logic. </success_criteria>