---
phase: 01-matrix-qa-polish
plan: 05
subsystem: matrix
tags: [matrix, confirmations, regression-testing, adapter]
requires:
  - phase: 01-matrix-qa-polish
    provides: Text confirmation flow and Matrix regression baseline from plans 01-03 and 01-04
provides:
  - Stable Matrix pending-confirm storage scoped by user id and room id
  - Matrix command callbacks that retain originating room context
  - Adapter-level confirm and cancel regressions covering send_outgoing round trips
affects: [matrix-adapter, matrix-tests, phase-01-closeout]
tech-stack:
  added: []
  patterns: [Matrix callback payloads carry room context, pending confirmations are keyed by user id plus room id]
key-files:
  created:
    - .planning/phases/01-matrix-qa-polish/01-05-SUMMARY.md
  modified:
    - adapter/matrix/bot.py
    - adapter/matrix/converter.py
    - adapter/matrix/handlers/confirm.py
    - adapter/matrix/store.py
    - tests/adapter/matrix/test_converter.py
    - tests/adapter/matrix/test_confirm.py
    - tests/adapter/matrix/test_send_outgoing.py
key-decisions:
  - "Matrix command callbacks now include room_id in payload for !yes and !no so confirm handlers can resolve runtime state without changing core protocol types."
  - "Pending confirmations are stored under the D-08 composite key of matrix user id plus room id, with a narrow legacy fallback only for callers that omit room context."
patterns-established:
  - "Matrix adapter send paths must derive transport-specific identity from room metadata before writing adapter-local state."
  - "Adapter regressions should use mismatched Matrix room ids and logical chat ids to catch scope drift."
requirements-completed: []
duration: 2 min
completed: 2026-04-03
---

# Phase 01 Plan 05: Matrix Confirmation Scope Summary

**Matrix confirmations now survive the real send_outgoing -> !yes/!no adapter round trip by keeping pending state scoped to the Matrix user and Matrix room.**

## Performance

- **Duration:** 2 min
- **Started:** 2026-04-03T09:26:32Z
- **Completed:** 2026-04-03T09:27:55Z
- **Tasks:** 2
- **Files modified:** 7

## Accomplishments

- Aligned the Matrix adapter runtime so command callbacks keep room context and pending confirmation state uses the D-08 `(user_id, room_id)` scope.
- Added a compatibility fallback in confirm handlers for legacy callers that do not send `payload["room_id"]`.
- Added adapter-level regressions for `OutgoingUI` -> `!yes` and `OutgoingUI` -> `!no` using distinct Matrix room ids and logical chat ids.

## Task Commits

Each task was committed atomically:

1. **Task 1: Preserve Matrix user-and-room identity through the `!yes` / `!no` callback path** - `35695e0` (fix)
2. **Task 2: Add end-to-end adapter regression tests for `send_outgoing` -> `!yes` / `!no`** - `716dec5` (test)

## Files Created/Modified

- `adapter/matrix/bot.py` - derives the Matrix user id from room metadata before persisting pending confirmations.
- `adapter/matrix/converter.py` - carries Matrix `room_id` in `IncomingCallback.payload` for `!yes` and `!no`.
- `adapter/matrix/handlers/confirm.py` - resolves pending confirmations by `(event.user_id, payload["room_id"])` with legacy fallback behavior.
- `adapter/matrix/store.py` - supports composite pending-confirm keys while remaining compatible with older single-key callers.
- `tests/adapter/matrix/test_converter.py` - asserts Matrix callbacks preserve logical `chat_id` and include `payload["room_id"]`.
- `tests/adapter/matrix/test_confirm.py` - validates composite-key confirm/cancel behavior and the legacy fallback path.
- `tests/adapter/matrix/test_send_outgoing.py` - exercises `send_outgoing` to confirm/cancel round trips under user-and-room scope.

## Decisions Made

- Kept the contract change inside the Matrix adapter by extending callback payloads instead of changing `core.protocol.IncomingCallback`.
- Preserved the old chat-id-only lookup only as a fallback path for older tests or non-room-aware callers.

## Deviations from Plan

None - plan executed exactly as written.

## Issues Encountered

None.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- The Phase 01 confirmation blocker from `01-VERIFICATION.md` is closed for the Matrix adapter runtime path.
- Phase 01 still needs the remaining plan work outside `01-05`, but this gap no longer blocks end-to-end `!yes` / `!no` behavior.

## Self-Check: PASSED

- Found `.planning/phases/01-matrix-qa-polish/01-05-SUMMARY.md`
- Found commit `35695e0`
- Found commit `716dec5`
