---
phase: 01-matrix-qa-polish
plan: 01
subsystem: matrix
tags: [matrix, matrix-nio, spaces, sqlite]
requires:
  - phase: 00-foundation
    provides: Matrix adapter baseline with room metadata helpers
provides:
  - Matrix pending-confirm store helpers keyed by room id
  - Space-first invite flow with user space metadata and dynamic chat ids
  - Space-aware room routing fallback for unregistered rooms
affects: [matrix invite flow, matrix chat creation, matrix confirmation flow]
tech-stack:
  added: []
  patterns: [space-first Matrix onboarding, room metadata without implicit auto-registration]
key-files:
  created: []
  modified:
    - adapter/matrix/store.py
    - adapter/matrix/handlers/auth.py
    - adapter/matrix/room_router.py
key-decisions:
  - "Invite idempotency now keys off user_meta.space_id instead of invite-room metadata."
  - "Unknown Matrix rooms return an explicit unregistered chat id instead of silently creating room metadata."
patterns-established:
  - "Matrix Space bootstrap creates a private Space, first chat room, and m.space.child link before welcoming the user."
  - "Per-room pending confirmation state is stored under a dedicated store prefix."
requirements-completed: []
duration: 1 min
completed: 2026-04-02
---

# Phase 01 Plan 01: Space+rooms infrastructure Summary

**Matrix Space-first onboarding now creates a private Space, seeds the first chat room, and stores pending confirmations by room id.**

## Performance

- **Duration:** 1 min
- **Started:** 2026-04-02T19:49:25Z
- **Completed:** 2026-04-02T19:50:50Z
- **Tasks:** 3
- **Files modified:** 3

## Accomplishments
- Added `pending_confirm` storage helpers without changing existing Matrix store behavior.
- Replaced the DM-first invite flow with Space creation, first-room linking, user invites, and dynamic `C*` chat ids.
- Stopped `resolve_chat_id` from auto-registering unknown rooms and made the fallback explicit in logs and returned ids.

## Task Commits

Each task was committed atomically:

1. **Task 1: Add pending_confirm helpers to store.py** - `9123401` (feat)
2. **Task 2: Rewrite handle_invite for Space+rooms** - `c2e29cc` (feat)
3. **Task 3: Update room_router.py for space-aware resolve** - `c8770da` (fix)

## Files Created/Modified
- `adapter/matrix/store.py` - Adds `PENDING_CONFIRM_PREFIX` plus get/set/clear helpers for confirmation state.
- `adapter/matrix/handlers/auth.py` - Rewrites invite handling to create a Space and first chat room, invite the user, and persist `space_id`.
- `adapter/matrix/room_router.py` - Resolves known chat ids from stored metadata only and warns on unregistered rooms.

## Decisions Made
- Used `user_meta.space_id` as the idempotency gate so repeated invites do not depend on whichever DM room triggered the event.
- Preserved the initial DM `join` before Space creation so the bot still accepts the invite room and keeps nio tracking consistent.
- Returned `unregistered:{room_id}` for unknown rooms instead of mutating store state from the router.

## Deviations from Plan

### Auto-fixed Issues

**1. [Rule 3 - Blocking] Updated planning state artifacts manually**
- **Found during:** Post-task metadata updates
- **Issue:** `gsd-tools state advance-plan` could not parse the repository's existing `STATE.md` schema, which blocked the required state update flow.
- **Fix:** Updated `STATE.md` and `ROADMAP.md` manually to reflect plan completion while preserving existing content.
- **Files modified:** `.planning/STATE.md`, `.planning/ROADMAP.md`
- **Verification:** Re-read both files after editing to confirm plan progress and decisions were recorded correctly.
- **Committed in:** metadata commit

---

**Total deviations:** 1 auto-fixed (1 blocking)
**Impact on plan:** No product scope change. The deviation only affected GSD metadata bookkeeping.

## Issues Encountered

- `gsd-tools state advance-plan` failed because the current `STATE.md` format does not include the fields the tool expects. Metadata was updated manually so execution could complete cleanly.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- Ready for `01-02-PLAN.md`, which can now rely on `space_id` in `user_meta` and non-mutating room resolution.
- No blockers introduced by this plan.

## Self-Check: PASSED

- Found `.planning/phases/01-matrix-qa-polish/01-01-SUMMARY.md` on disk.
- Verified task commits `9123401`, `c2e29cc`, and `c8770da` in `git log`.
