I2981 — A board or journal change is pushed over one WebSocket
Give the board and the mesh journal one change generation (crate::change), advanced by every board mutation and every journal append or ingest, and carry the blackboard on the one live channel: GET /events?follow=blackboard sends stream.ready with the server epoch, the snapshot, then a new snapshot whenever what it says changed and the monitor signals after the connection cursor; a resumed connection sends after and epoch, and a cursor of another process or one the monitor cannot page through is answered with stream.resync and a fresh snapshot. One read per generation is shared by every connection; a frame says whether a change pushed it or a refresh found it.
BLOCKED wave 1 · p1 · implementation profile · runs alone
Part of peer-blackboard — The peer blackboard is one projection, pushed live to every surface.
Blocked. This issue cannot start until I2980 is done. The status is derived from that, not declared.
Objective
Give the board and the mesh journal one change generation (crate::change), advanced by every board mutation and every journal append or ingest, and carry the blackboard on the one live channel: GET /events?follow=blackboard sends stream.ready with the server epoch, the snapshot, then a new snapshot whenever what it says changed and the monitor signals after the connection cursor; a resumed connection sends after and epoch, and a cursor of another process or one the monitor cannot page through is answered with stream.resync and a fresh snapshot. One read per generation is shared by every connection; a frame says whether a change pushed it or a refresh found it.
Why
/cockpit/monitor polls the whole monitor every five seconds per tab, and the board changes nobody hears about until the next poll or the cooperation tick.
Current state
No change notification exists in the board, the journal or the monitor; /events is wired to the execution store.
Desired state
A peer's announce reaches a connected socket in under a second at P95 on this machine, measured.
Scope
- apps/majordomus-cli/src/change.rs
- apps/majordomus-cli/src/lib.rs
- apps/majordomus-cli/src/peers.rs
- apps/majordomus-cli/src/mesh/journal.rs
- apps/majordomus-cli/src/http/events.rs
- apps/majordomus-cli/src/http/follow.rs
- apps/majordomus-cli/src/http/mod.rs
- apps/majordomus-cli/src/http/router.rs
- apps/majordomus-cli/src/monitor/mod.rs
- apps/majordomus-cli/src/capability/builtin/blackboard.rs
- .ai/repo/adrs/0176-the-blackboard-is-one-projection-pushed-over-one-socket.md
- docs/BLACKBOARD.md
- test/cases/3381_the_blackboard_is_pushed.sh
Dependencies
What waits on this
Acceptance criteria
- An announce, a claim and a review each reach a connected client as a frame without a poll
- A reconnect with the last cursor repeats nothing; a refused cursor resynchronises
- A slow client is told it lagged and never holds an unbounded queue
Validation
- majordomus plan validate
- bash test/run.sh 3381_the_blackboard_is_pushed
Evidence required
- case_blackboard_pushed
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I2981.yaml. Read it back with majordomus plan show I2981.