Handle leading mentions in Matrix messages #60

Merged
dev-agent merged 1 commits from matrix-mentions into main 2026-09-29 16:01:08 +00:00
Collaborator

Found on the live end-to-end run: Nisse Dev Testing: re-plan wasn't recognised as re-plan, because the Matrix transport passed the client's mention prefix through as part of the text. The same would have made an addressed approve count as rejection feedback, which throws the plan away and re-plans.

Changes (nisse-dev/src/nisse_dev/matrix.py, transport.py, control.py)

  • Leading mention of the agent → removed before command matching. Recognised forms: an HTML mention pill in formatted_body (it carries the exact user ID), the agent's user ID, or its display name followed by :. The display name is learnt from the agent's own m.room.member event in sync, so no extra endpoint is used.
  • Leading mention of anyone else → the message is skipped. In a shared room, Nisse Ops: approve or @alice:…: looks good is addressed elsewhere and must not reach this agent as gate input.
  • Only the start of the message counts. approve, cc @alice is unchanged.
  • The record keeps what was sent. InboundMessage gains an optional original, and the canonical log stores it; command matching uses the stripped text.

Sender verification is unchanged. The sender still comes from the event's sender field, set by the homeserver from the authenticated session. The operator allowlist and gates check that field only, never the text.

Tests: five new transport cases (pill, typed display name, typed user ID, someone else's mention skipped, mention mid-text left alone) and one orchestrator case (matched as stripped, recorded as sent). The new cases fail on main, except the mid-text one, which guards against over-stripping. 431 unit tests and the live Matrix test pass; lint and format clean.

🤖 Generated with Claude Code

Found on the live end-to-end run: `Nisse Dev Testing: re-plan` wasn't recognised as `re-plan`, because the Matrix transport passed the client's mention prefix through as part of the text. The same would have made an addressed `approve` count as rejection feedback, which throws the plan away and re-plans. **Changes** (`nisse-dev/src/nisse_dev/matrix.py`, `transport.py`, `control.py`) - **Leading mention of the agent → removed before command matching.** Recognised forms: an HTML mention pill in `formatted_body` (it carries the exact user ID), the agent's user ID, or its display name followed by `:`. The display name is learnt from the agent's own `m.room.member` event in sync, so no extra endpoint is used. - **Leading mention of anyone else → the message is skipped.** In a shared room, `Nisse Ops: approve` or `@alice:…: looks good` is addressed elsewhere and must not reach this agent as gate input. - **Only the start of the message counts.** `approve, cc @alice` is unchanged. - **The record keeps what was sent.** `InboundMessage` gains an optional `original`, and the canonical log stores it; command matching uses the stripped text. **Sender verification is unchanged.** The sender still comes from the event's `sender` field, set by the homeserver from the authenticated session. The operator allowlist and gates check that field only, never the text. **Tests:** five new transport cases (pill, typed display name, typed user ID, someone else's mention skipped, mention mid-text left alone) and one orchestrator case (matched as stripped, recorded as sent). The new cases fail on `main`, except the mid-text one, which guards against over-stripping. 431 unit tests and the live Matrix test pass; lint and format clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dev-agent added 1 commit 2026-09-29 15:59:28 +00:00
Handle leading mentions in Matrix messages
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m24s
b0c5f48be4
Clients put the addressee's name in front of a message that mentions
it ("Nisse Dev Testing: re-plan"), and the transport passed that text
on whole, so no command matched: the live run's re-plan was asked again,
and an addressed 'approve' would have counted as rejection feedback.

- A leading mention of the agent (an HTML pill, its user ID, or its
  display name followed by ':') is removed before commands are matched.
  The display name is learnt from the agent's own member event.
- A message whose leading mention is someone else is skipped: in a
  shared room it is addressed to another agent or person.
- Only the start counts; a mention later in the text is left alone.
- The transcript records the message as sent (InboundMessage.original).

The sender is unaffected: it still comes from the event's homeserver-set
sender field, never from the text.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dongar approved these changes 2026-09-29 16:00:10 +00:00
dev-agent merged commit 8283e9eb1c into main 2026-09-29 16:01:08 +00:00
dev-agent deleted branch matrix-mentions 2026-09-29 16:01:08 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dev/nisse#60