Completes build-order step 2: the real transport behind the interface PR A established.
matrix.py — MatrixTransport implementing Transport over the Matrix client-server HTTP API directly: token auth, /sync long-poll in a background thread, /send with unique txn IDs. Deviation from the presented plan: I proposed matrix-nio, but the used surface is four endpoints, and going direct avoids both the SDK dependency and an asyncio-in-thread bridge around our synchronous orchestrator — httpx was already in the tree. If you'd rather have nio (its strongest argument: the [e2e] extra when encryption lands), the swap is contained in this one file.
A1 semantics honored: the first sync learns the stream position and never delivers backlog — room history cannot become load-bearing context. Own messages and non-message events are filtered; the sender MXID rides through for the orchestrator's operator allowlist.
Outage posture per B2: the sync loop backs off exponentially (capped 60s) and retries forever; an outage delays reactions, never fails anything.
Encrypted rooms are not supported — per operator decision the bot rooms are created unencrypted until E2E support lands (the original room was recreated; encryption can be turned on in-place later, since Matrix's switch is one-way in the safe direction).
Test-room isolation: the live smoke test binds only to NISSE_MATRIX_TEST_ROOM_ID (new, documented in .env.example) — never the production room. Verified against the real homeserver: the smoke test's message landed in nisse-dev-testing.
Deferred, will note in follow-ups: thread-relation support for plan discussions and reply-relation approval binding — the orchestrator only opens one gate at a time today, so bare approve is unambiguous by construction; threading lands when the executor loop makes multi-message plan discussions real.
8 new unit tests over a mocked HTTP layer (send shape/auth/txn uniqueness, backlog skip, self/non-message filtering, config errors). 75 unit + 7 integration green locally, both live smoke tests (LiteLLM and Matrix) included.
Completes build-order step 2: the real transport behind the interface PR A established.
- **`matrix.py`** — `MatrixTransport` implementing `Transport` over the Matrix client-server HTTP API directly: token auth, `/sync` long-poll in a background thread, `/send` with unique txn IDs. **Deviation from the presented plan**: I proposed matrix-nio, but the used surface is four endpoints, and going direct avoids both the SDK dependency and an asyncio-in-thread bridge around our synchronous orchestrator — `httpx` was already in the tree. If you'd rather have nio (its strongest argument: the `[e2e]` extra when encryption lands), the swap is contained in this one file.
- **A1 semantics honored**: the first sync learns the stream position and never delivers backlog — room history cannot become load-bearing context. Own messages and non-message events are filtered; the sender MXID rides through for the orchestrator's operator allowlist.
- **Outage posture per B2**: the sync loop backs off exponentially (capped 60s) and retries forever; an outage delays reactions, never fails anything.
- **Encrypted rooms are not supported** — per operator decision the bot rooms are created unencrypted until E2E support lands (the original room was recreated; encryption can be turned on in-place later, since Matrix's switch is one-way in the safe direction).
- **Test-room isolation**: the live smoke test binds only to `NISSE_MATRIX_TEST_ROOM_ID` (new, documented in `.env.example`) — never the production room. Verified against the real homeserver: the smoke test's message landed in `nisse-dev-testing`.
- **Deferred, will note in follow-ups**: thread-relation support for plan discussions and reply-relation approval binding — the orchestrator only opens one gate at a time today, so bare `approve` is unambiguous by construction; threading lands when the executor loop makes multi-message plan discussions real.
8 new unit tests over a mocked HTTP layer (send shape/auth/txn uniqueness, backlog skip, self/non-message filtering, config errors). 75 unit + 7 integration green locally, both live smoke tests (LiteLLM and Matrix) included.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- matrix.py: Transport implementation over the Matrix client-server
HTTP API directly (token auth, /sync long-poll, /send) using the
existing httpx dependency — no Matrix SDK; four endpoints total.
Deviation from the presented plan (matrix-nio) flagged in the PR
- First sync learns position and skips backlog, so room history is
never delivered as context (A1); own messages and non-message
events filtered; sender MXID passed through for the orchestrator's
operator allowlist
- Sync loop backs off (capped at 60s) and retries indefinitely on
homeserver errors, mirroring B2's polling posture
- Encrypted rooms unsupported: bot rooms are created unencrypted
until E2E lands (operator decision; room recreated accordingly)
- NISSE_MATRIX_TEST_ROOM_ID added: the live smoke test binds only
to the dedicated test room, never the production room
- 8 unit tests over a mocked HTTP layer; live integration test
verified against the real homeserver
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Completes build-order step 2: the real transport behind the interface PR A established.
matrix.py—MatrixTransportimplementingTransportover the Matrix client-server HTTP API directly: token auth,/synclong-poll in a background thread,/sendwith unique txn IDs. Deviation from the presented plan: I proposed matrix-nio, but the used surface is four endpoints, and going direct avoids both the SDK dependency and an asyncio-in-thread bridge around our synchronous orchestrator —httpxwas already in the tree. If you'd rather have nio (its strongest argument: the[e2e]extra when encryption lands), the swap is contained in this one file.NISSE_MATRIX_TEST_ROOM_ID(new, documented in.env.example) — never the production room. Verified against the real homeserver: the smoke test's message landed innisse-dev-testing.approveis unambiguous by construction; threading lands when the executor loop makes multi-message plan discussions real.8 new unit tests over a mocked HTTP layer (send shape/auth/txn uniqueness, backlog skip, self/non-message filtering, config errors). 75 unit + 7 integration green locally, both live smoke tests (LiteLLM and Matrix) included.
🤖 Generated with Claude Code