surfaces/.planning/phases/05-mvp-deployment/05-01-PLAN.md

9.3 KiB

phase plan type wave depends_on files_modified autonomous requirements must_haves
05-mvp-deployment 01 execute 1
adapter/matrix/reconciliation.py
adapter/matrix/bot.py
tests/adapter/matrix/test_reconciliation.py
tests/adapter/matrix/test_restart_persistence.py
true
PH05-01
PH05-03
truths artifacts key_links
On restart, existing Matrix Space and child-room topology is rebuilt before live sync begins.
Restart recovery preserves Space+rooms UX instead of creating duplicate DM-style working rooms.
Recovered rooms regain user metadata, room metadata, and chat bindings needed for normal routing.
Legacy working rooms missing `platform_chat_id` are backfilled deterministically during startup before strict routing handles traffic.
path provides
adapter/matrix/reconciliation.py Authoritative restart reconciliation from Matrix topology into local metadata
path provides
adapter/matrix/bot.py Startup wiring that runs reconciliation before sync_forever
path provides
tests/adapter/matrix/test_reconciliation.py Regression coverage for startup recovery and idempotence
from to via pattern
adapter/matrix/bot.py adapter/matrix/reconciliation.py startup bootstrap before sync_forever reconcil
from to via pattern
adapter/matrix/reconciliation.py core/chat.py chat manager rebuild for recovered rooms get_or_create
Rebuild Matrix-local routing state from authoritative Space topology before the bot processes live traffic.

Purpose: Preserve the Phase 01 Space+rooms contract after restart even if SQLite metadata is partial or missing. Output: A startup reconciliation module, bot wiring, and regression tests proving no DM-first duplication on restart.

<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/05-mvp-deployment/05-RESEARCH.md @.planning/phases/05-mvp-deployment/05-VALIDATION.md @.planning/phases/04-matrix-mvp-shared-agent-context-and-context-management-comma/04-02-SUMMARY.md @adapter/matrix/bot.py @adapter/matrix/store.py @adapter/matrix/handlers/auth.py @tests/adapter/matrix/test_invite_space.py @tests/adapter/matrix/test_chat_space.py @tests/adapter/matrix/test_restart_persistence.py From `adapter/matrix/bot.py`:
async def prepare_live_sync(client: AsyncClient) -> str | None:
    response = await client.sync(timeout=0, full_state=True)
    if isinstance(response, SyncResponse):
        return response.next_batch
    return None
class MatrixBot:
    async def _bootstrap_unregistered_room(
        self,
        room: MatrixRoom,
        sender: str,
    ) -> list[OutgoingEvent] | None: ...

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: ...
async def next_platform_chat_id(store: StateStore) -> str: ...
Task 1: Add restart reconciliation regression coverage tests/adapter/matrix/test_reconciliation.py, tests/adapter/matrix/test_restart_persistence.py tests/adapter/matrix/test_invite_space.py, tests/adapter/matrix/test_chat_space.py, tests/adapter/matrix/test_restart_persistence.py, adapter/matrix/bot.py, adapter/matrix/handlers/auth.py, .planning/phases/05-mvp-deployment/05-RESEARCH.md - Test 1: startup recovery rebuilds user space metadata, room metadata, and chat bindings from Matrix topology without creating new working rooms (per D-Phase05-reset and PH05-01). - Test 2: reconciliation is idempotent and safe when local SQLite state is already present. - Test 3: reconciliation happens before lazy `_bootstrap_unregistered_room()` would run for existing rooms (per PH05-03). - Test 4: legacy room metadata missing `platform_chat_id` is backfilled deterministically at startup and persisted before routed handling begins. - `tests/adapter/matrix/test_reconciliation.py` exists and names reconciliation entrypoints explicitly. - The new tests assert restored `space_id`, `chat_id`, `matrix_user_id`, and `platform_chat_id` values for recovered rooms. - The regression slice also proves existing Space onboarding behavior still passes by running `test_invite_space.py` and `test_chat_space.py`. - The automated command in `` fails before implementation or would fail if reconciliation is removed. Create a dedicated `tests/adapter/matrix/test_reconciliation.py` module and extend restart persistence coverage so Phase 05 has a real Wave 0 contract. Model the recovered topology after the Phase 01 Space+rooms onboarding tests, not a DM-first flow, and explicitly keep those onboarding regressions in the verification slice so restart hardening cannot break provisioning UX. Cover recovery of `user_meta`, `room_meta`, `ChatManager` bindings, and room-local routing fields from Matrix-side state before live callbacks begin, including deterministic backfill for legacy rooms that predate `platform_chat_id`. Keep temporary UX state out of scope, per research. pytest tests/adapter/matrix/test_invite_space.py tests/adapter/matrix/test_chat_space.py tests/adapter/matrix/test_reconciliation.py tests/adapter/matrix/test_restart_persistence.py -v Phase 05 has failing-or-red-before-code tests that define authoritative restart reconciliation behavior and exclude duplicate room provisioning. Task 2: Implement authoritative startup reconciliation and wire it before live sync adapter/matrix/reconciliation.py, adapter/matrix/bot.py adapter/matrix/bot.py, adapter/matrix/store.py, adapter/matrix/handlers/auth.py, tests/adapter/matrix/test_reconciliation.py, tests/adapter/matrix/test_restart_persistence.py, .planning/phases/05-mvp-deployment/05-RESEARCH.md - Test 1: startup rebuild runs after login and initial full-state fetch, but before `sync_forever()` processes live events. - Test 2: recovered rooms keep their existing Space+rooms identity and do not trigger `_bootstrap_unregistered_room()` unless the room is genuinely new. - Test 3: local metadata can be rebuilt from Matrix topology when SQLite entries are missing, while existing valid metadata remains stable. - Test 4: startup repair assigns a deterministic `platform_chat_id` to legacy rooms missing that field and persists it before routed platform calls can occur. - `adapter/matrix/reconciliation.py` exports a focused reconciliation entrypoint used by startup code. - `adapter/matrix/bot.py` invokes reconciliation before `client.sync_forever(...)`. - Recovered room metadata includes `room_type`, `chat_id`, `space_id`, `matrix_user_id`, and `platform_chat_id` where available or rebuildable. - Legacy rooms missing `platform_chat_id` follow one documented startup backfill path rather than ad hoc routing fallbacks. Implement a restart recovery module that treats Matrix topology as authoritative, per the Phase 05 reset and research notes. Rebuild missing local metadata for Space-owned working rooms, deterministically backfill missing `platform_chat_id` values for legacy rooms, and re-create `ChatManager` entries needed by routing, while keeping SQLite as a rebuildable cache rather than the source of truth. Wire the new reconciliation step into startup after the initial full-state sync and before live sync begins, and keep the onboarding regression slice green while doing it. Do not widen into timeline scraping, new storage backends, or DM-first fallbacks. pytest tests/adapter/matrix/test_invite_space.py tests/adapter/matrix/test_chat_space.py tests/adapter/matrix/test_reconciliation.py tests/adapter/matrix/test_restart_persistence.py tests/adapter/matrix/test_dispatcher.py -v Restart recovery restores the minimum durable state for existing Space rooms before live traffic, and the guarded regression suite passes. Run the onboarding, reconciliation, restart-persistence, and Matrix dispatcher slices together. Confirm startup now has a deterministic pre-sync recovery and legacy-room backfill step instead of relying on lazy room bootstrap or routing-time fallbacks for existing topology.

<success_criteria> The bot can restart with partial or empty local room metadata, rebuild managed Space rooms before live sync, and continue handling those rooms without creating duplicate onboarding rooms. </success_criteria>

After completion, create `.planning/phases/05-mvp-deployment/05-01-SUMMARY.md`