M4b spec: approvals from non-approvers in direct messages go to an approver, with who asked and what
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
# M4b design: approvals over Mattermost
|
# M4b design: approvals over Mattermost
|
||||||
|
|
||||||
Status: approved by the owner, 2026-09-24, with P16 applied to the brief. It builds on M4a
|
Status: approved by the owner, 2026-09-24, with P16 applied to the brief. Changed after the review
|
||||||
|
of the same day (owner's decision): approvals asked by non-approvers in direct or group messages
|
||||||
|
are redirected to an approver with who asked and their message (section 6). It builds on M4a
|
||||||
(`docs/specs/2026-09-23-m4a-gateway.md`, section 12 there is the agreed outline) and M3a's approval
|
(`docs/specs/2026-09-23-m4a-gateway.md`, section 12 there is the agreed outline) and M3a's approval
|
||||||
path (`docs/specs/2026-09-18-m3a-decision-path.md`, section 6). Owner's decisions of 2026-09-24,
|
path (`docs/specs/2026-09-18-m3a-decision-path.md`, section 6). Owner's decisions of 2026-09-24,
|
||||||
changing the outline: **no reactions**, answers are commands only; an `[approvals] users` list
|
changing the outline: **no reactions**, answers are commands only; an `[approvals] users` list
|
||||||
@@ -161,10 +163,33 @@ One thread per accepted `gateway.sock` connection. It reads frame 1 (bounded by
|
|||||||
checks the ids in it, and decides **where**:
|
checks the ids in it, and decides **where**:
|
||||||
|
|
||||||
- If the session is `mm-<root>` and `state.in_flight` holds a turn of that session, the approval
|
- If the session is `mm-<root>` and `state.in_flight` holds a turn of that session, the approval
|
||||||
goes into that turn's thread (its channel and root). This covers direct messages and channels.
|
goes into that turn's thread (its channel and root), **unless** the turn was asked by someone
|
||||||
|
who is not an approver in a direct or group message: no approver could answer it there. (In a
|
||||||
|
channel an approver can reply in the thread, so it stays.)
|
||||||
|
- A redirected approval (asked by a non-approver in a direct or group message) goes to the first
|
||||||
|
approver's direct channel as a new thread whose **first post** says who asked, where, and what
|
||||||
|
they asked (review of 2026-09-24, owner's requirement: the approver must know who is asking,
|
||||||
|
their prompt, and what Boxmaker is trying to do):
|
||||||
|
|
||||||
|
````text
|
||||||
|
**Approval 3** was asked by @alex in a direct message with the bot. Their message:
|
||||||
|
```
|
||||||
|
Read the file /srv/notes/q3.txt and summarise it.
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
The message is the text of the turn that asked (a burst, joined), escaped and fenced like the
|
||||||
|
arguments; it is context, not what is approved, so it is cut at 2,000 characters with
|
||||||
|
`(… <n> more characters)` after the fence. The approval's own posts follow in that thread, and
|
||||||
|
the asking thread gets one line: `waiting for approval <id>: it was sent to an approver`.
|
||||||
- Otherwise (`bxctl chat`, a session no longer in flight, later scheduled jobs), it goes to the
|
- Otherwise (`bxctl chat`, a session no longer in flight, later scheduled jobs), it goes to the
|
||||||
first approver's direct channel (`POST /channels/direct`), as a new top-level post whose own
|
first approver's direct channel as a new thread whose first post says
|
||||||
thread is where it is answered.
|
`**Approval <id>** was asked in session `<session>`, which gatewayd does not follow now (a
|
||||||
|
restart, or a session from outside Mattermost).`, followed by the approval's posts.
|
||||||
|
|
||||||
|
`gatewayd` knows who asked from the posts it queued: for each session it keeps the author of the
|
||||||
|
last message queued, the channel's type, and, when a turn starts, that turn's text; it forgets them
|
||||||
|
when the turn ends. They are not in the state file: after a restart the turn is interrupted anyway.
|
||||||
|
|
||||||
### The text
|
### The text
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user