Skip to main content

Module msg

Module msg 

Source
Expand description

Messages between sessions: <store>/messages.jsonl, one line per borg tell or borg ask, from a session on any harness (or the engineer’s terminal) to the sessions on this machine (local, written local@<node>), every session of the collective on every member’s machine (collective, or its synonym all, written all as it always was), one session on one node (<session>@<node>), or the engineer (engineer[:<email>]): an Address, parsed in one place. Local first: a local line never leaves this machine (borg-mesh lines.rs travels keeps it here), and a drone named on the command line is this machine’s when one here matches; a colleague’s session is reached by its node, by collective, or as the sender of what a reply answers. A 0.4.0 reader parses local@<node> as the session local of that node, which no session is: it reaches nobody there. Plain lines, each naming its node, so the mesh can union them like the other synced logs; on one machine they need no mesh. A borg pause, borg resume or a remote borg no is a message too, of a privileged Kind that counts only under an admitted role (steer.rs).

A drone named on the command line (a designation as borg top shows it, or a session id prefix) is resolved to its session id when the message is sent: designations (“Two of Five”) shift as sessions start and end and differ per node, a session id does not. A line’s by, name and harness are its sender’s claims; only its node is checked (borg-mesh lines.rs travels), so a session is addressed with its node, and a reply goes to the (node, by) pair of what it answers (address): a by that names a local session from another node never routes a reply here.

Delivery (deliver): a recipient’s next prompt or tool call, where its harness takes context there (harness Caps), shows each message once, as labelled peer data with the command that answers it, never as the user’s words, never to its sender. What one event shows fits the harness’s context budget (Caps::context_chars, shared with what the hook already answers), newest first; the rest stay unclaimed for the next event, and a message longer than the budget shows its head and borg inbox --show <id>. A broadcast reaches the sessions that were running when it was sent (as steer.rs applies). A delivery is claimed by creating <store>/messages/seen/<session>/<id> exclusively, so hooks running at once show it once, and acknowledged with a Seen line in the log; a claim no Seen of its session lists (a 0.5.0 hook’s, which wrote none, or one whose acknowledgement failed) is acknowledged at the session’s next read of the log. Nothing sent: the hook costs one failed stat; no tell, ask or steer written since the session’s last look, a read of its SCANNED stamp and of the log’s GENERATION more. Acknowledgements do not count as a change (its own, another session’s, one merged from the mesh), nor does the cut of lines past the TTL a write makes (Change::Expired): every writer of this version records whether it wrote talk or cut a line a reader may use (wrote), and a log written by anything else is read again (talk). A prompt whose context the harness drops ("context": false) and a subagent’s event (agent_id) show nothing: the messages wait for the session itself.

Every line is checked on read (Message::well_formed, Seen::well_formed): the log syncs from every member, and its fields reach prompts, a shell command and terminals. Text is redacted (notes.rs redact) and kept whole up to WIRE_TEXT before it is hashed into the id; a text that fits V1_TEXT is written as a v1 line, which 0.5.0 readers read too.

Pacing (window_for): a sender may have a window of tells and asks to one recipient that it has not acknowledged, by a Seen line its recipient wrote when shown them or by a reply. The window starts at 1, doubles per acknowledged message, halves per message that expired unacknowledged, and is capped (WINDOW_CAP). Acknowledgements pace only a recipient they can be expected from (Pace): a broadcast (whoever runs when it is sent, maybe nobody) and the engineer (who may read where nothing acknowledges) are never paced more strictly than 0.5.0 paced them (V1_RATE_MS), and a session of another node is paced by that rate alone until its node acknowledges one of the sender’s messages to it (it may run 0.5.0, which never does). That cold start reads the pair’s own lines, which sync, not the mesh’s record of what each node reads (presence.rs reads, local and different on every node), so the window is a function of the lines alone, and once a Seen line of that node lists one of the pair’s messages, that pair is under its window on every node holding it. send decides by the window, over the log it writes to (under its lock), and also refuses a message that would push out one admitted before it (an earlier stamp, from a clock that stepped back or a send that took the lock later) or one of its sender’s unread messages to the same recipient (MEMBER_BYTES). The TTL and the bound later remove the earlier lines a window was decided by, so a replay can admit less than send did; what travels is decided by a bound every window keeps and that reads no earlier line (within_windows), so a line once written stays admitted on every node while it is held. A steer is never paced: a pause is answered by a resume. A Seen line is never shown, never paced, and no reader that counts messages counts it: it does not parse as a Message.

Bounded on write (bound): a line past TTL_MS goes, and of each member’s lines the newest of each class (conversation, steers, seen) stay while they fit MEMBER_BYTES, byte for byte as they were.

Structs§

Author
Who wrote a line: its sender (or the recipient a Seen speaks for) on the node the line names.
Message
One message of messages.jsonl.
Seen
What a recipient was shown: one line per delivery event (a hook’s, borg inbox’s) listing the ids of the tells and asks it showed, written by the recipient’s node. It acknowledges them (window_for) and does nothing else: never shown, never paced, bounded in its own class (bound), and its kind is no Kind, so it never parses as a Message and no reader that counts messages (unread counts, the inbox, the feed, borg listen, a 0.5.0 node) counts it.
Sender
Who sends a message.
Shown
One message as an event shows it: whole, or head, the start of its text (capped).
Shows
How one event shows its messages: to whom, on which harness, under which steering roles.
Window
One sender’s window to one recipient at a moment (window_for).

Enums§

Address
Whom a message is for, as its to says it (parse; Display writes it back).
Change
How a writer changed the log (wrote).
Kind
What a message does. Tell and Ask are conversation; Pause, Resume and Veto steer their recipient and count only under an admitted role (steer.rs). A line of any other kind does not parse as a Message; a Seen line (kind SEEN) is read as one by Line::parse alone.
Line
One well-formed line of messages.jsonl as this version reads it.
NoSteer
Why this node’s steer would not count on another node: borg-mesh steer.rs check on its own key.
Pace
How one sender’s tells and asks to one recipient are paced (window_for): by acknowledgements where they can be expected, else never more strictly than 0.5.0 paced them (V1_RATE_MS).
SendError
Why a message was not sent.

Constants§

ALL
Every session of the collective on every member’s machine (Address::All): the command word, a synonym of COLLECTIVE, and how a line writes it.
ASK
A message that asks for a reply.
COLLECTIVE
The command word for every session of the collective (Address::All, written all).
ENGINEER
The engineer’s terminal as sender and address: engineer:<git user.email>, or this alone.
FILE
The log, in the collective’s store.
FLAGS
borg tell and borg ask’s flags (completions.rs).
INBOX_FLAGS
borg inbox’s flags.
LOCAL
The command word for the sessions on this machine (Address::Local, written local@<node>).
MEMBER_BYTES
Guard: the bytes of one member’s lines of one class (conversation, steers, seen, and apart those for its own sessions: Class) the log keeps, the newest (bound). It stops one member’s flood from growing the file every hook and borg listen read; a class has its own, so tells never push out a pause or the acknowledgements that pace them. 0.5.0’s whole log held at most ~0.7 MB (500 lines of ~1.4 KB); a week of ordinary traffic from one member (lines of 0.3–1.5 KB) fits with room for long texts. A cut is counted (stats::MSG_DROPPED, why bounds), so a bound that binds often shows.
NAME
Protocol: the longest sender name a line holds; well_formed refuses a longer one.
NODE_CHARS
Display: the characters of a node key a label shows (short_node, the one routine every label of a node key calls: a delivered line, steer.rs who, presence.rs Mismatch::line, borg-mesh main.rs short): enough to tell the members of a team apart.
SEEN
The kind a Seen line names: not a Kind, so it never parses as a Message.
SEEN_IDS
Protocol and guard: the most ids one Seen line lists (a delivery that shows more writes more lines), so a line stays under ~4 KB and a forged one cannot list millions.
SESSION_CHARS
Display: the characters of a session id a label shows for a sender that gave no name (sender_label): enough to tell the sessions of one node apart.
SKEW_MS
How far ahead of this clock a message may be and still count. Protocol: the one clock skew between members borg allows; steer.rs SLACK_MS and borg-mesh live.rs derive from it, so changing it moves both.
STEER_FLAGS
borg pause and borg resume’s flags.
TELL
A message that informs.
TTL_MS
A message is conversation: shown and kept for a week. Protocol: every member drops a line older than this (fresh), so they keep the same lines.
USAGE
V1_RATE_MS
Protocol: 0.5.0’s pacing (its RATE_MS), one tell or ask per sender and recipient this often, the earliest first: all a borg/mesh/13 node takes (borg-mesh sync.rs v1_window). It paces a session of a node that acknowledges nothing (Pace::Rate) and floors the window of a recipient whose reading may write no acknowledgement (Pace::Floor), so where an acknowledgement may never come no sender is paced more strictly than 0.5.0 paced it. Also the span over which the mesh bounds one sender’s unread messages to one recipient (within_windows).
V1_TEXT
Protocol: a v1 line’s text, 0.5.0’s bound: at most this many characters, plus an ellipsis when 0.5.0 cut it. A text that fits is written as v1 (Message::new), so 0.5.0 readers and borg/mesh/13 peers read it; a longer one is a v2 line, which they drop.
WINDOW_CAP
Derived: the doubling’s ceiling (window_for), as many full texts (WIRE_TEXT, at a byte per character) as one member’s share of the log (MEMBER_BYTES) holds. It promises no room: a line takes more than its text (its fields, up to 4 bytes a character), and the share is the node’s, across all its senders and recipients. So send refuses a message that would push one of its sender’s unread messages to the same recipient out of the log (SendError::Share); another pair’s newer lines may still push it out, oldest first, and that cut is counted (stats::MSG_DROPPED, why bounds). Also what the mesh lets through unread from one sender to one recipient within one V1_RATE_MS (within_windows): no window lets more.
WIRE_TEXT
Protocol: a v2 line’s text, kept whole up to this many characters, plus an ellipsis past it. Part of well_formed, so every member reads the same lines; never changed within a line version. Also a guard: one text of about 4,000 tokens (a page of findings, a plan), longer than any harness takes into one event, so what shows is the delivery budget’s choice (deliver), not the format’s, while one member’s share (MEMBER_BYTES) still holds WINDOW_CAP full texts.

Functions§

ack
Acknowledges that by (a session, or engineer[:<email>]) of this node was shown the tells and asks ids at now: Seen lines of at most SEEN_IDS ids each, written under the log’s lock and bounded as send bounds it. Counts no message: only a bound’s cut is counted. Nothing for a by a line cannot carry, whom every reader would drop. The lines leave the log’s talk as it was (wrote), and so does a cut of lines past the TTL they cause (Change::Expired), so they make no reader read the log again; only a cut by MEMBER_BYTES moves it (Change::Cut).
ack_engineer
Acknowledges, as the engineer of the repo at cwd (engineer:<git user.email>), the messages to the engineer among shown, which a view put in front of them, that no Seen of theirs on this node lists yet (engineer_acks): the terminal inbox calls it, and so may any view that shows the engineer a message’s text (borg top, borg web).
bound
What the log keeps of lines (its lines in order) at now: none past TTL_MS (with steer.rs SLACK_MS) or without an ms, and of each member’s lines (by the node a line names) of each Class the newest while they fit MEMBER_BYTES. Newest by stamp, then by the line itself, so every node holding the same lines keeps the same whatever order they arrived in; a node’s lines for its own sessions have classes of their own, so its peers, which never hold them, keep what it keeps of the lines that travel. The kept lines stay byte for byte, in their order. Returns them and how many the bytes bound cut. send and the mesh (borg-mesh sync.rs store_lines) bound the log by it alone.
deliver
The hook’s call after everything else answered (out): at a prompt or tool call where the harness takes context, the messages for the event’s session not shown yet join the answer’s context, each once. A block (decision) answers the event alone, a prompt sent with "context": false (opencode during a stop) drops what borg answers, and a subagent’s event (agent_id: Claude gives its context to the subagent) is not the session’s: the messages wait. What shows fits the harness’s context budget (Caps::context_chars) less what out already holds (capped), newest first; the rest wait, and the session’s SCANNED stamp is not written while any does. The tells and asks shown are acknowledged (ack), with those an earlier event claimed that no Seen of the session lists (owed), and the answer names the tells and asks it showed ("shown_ids", for adapters: a wake names the same ids, listen.rs say, so an adapter drops a held wake only once every message it names was shown; never a count, since one event may show a newer message and leave a held wake’s). The stamp holds the log’s talk as the call found it, before it read the log (talk): Seen lines written since, its own acknowledgement’s or any other session’s or node’s, leave it, a tell, ask or steer moves it. None is written when the acknowledgement failed, so the next call tries it again. started: the session’s start (presence.rs); None still delivers messages to the session but no broadcast.
for_session
The conversation of msgs (tells and asks; a steer is deliver’s alone) for session of the node here (started at started) at now, oldest first.
forget_session
Removes the delivery claims of one session (its presence record was pruned).
fresh
Whether m counts at now: not past TTL_MS, not further ahead than SKEW_MS.
fresh_at
Whether a line stamped ms counts at now, as fresh decides for a message.
is_engineer
Whether the address or sender a is the engineer: engineer or engineer:<email>.
is_id
Whether s is a message id as id_of writes it.
lines
Every well-formed line of the store, messages and Seen lines, in file order (Line::parse).
main
borg tell|ask|pause|resume|inbox ….
mark_of
The mark of the file at p (mark); None when there is none.
node
This node as a message names it: the member key borg-mesh publishes (node_pub_path), which the mesh checks a message’s node against before it carries it, else (no mesh yet) the stats.rs node.
node_pub_path
<store>/mesh/node.pub: where borg-mesh publishes this node’s member key (its identity.rs public_path is this).
path
read
Every well-formed message of the store, in file order: unparsable, newer, forged and Seen lines skipped.
render
The block of messages, with the reminder of what they are.
seen_by
Every id shown, with the sessions (as file names) it was shown to (top.rs, borg-web).
seen_path
Where the shown-once claims live, one directory per session (a watch on it sees deliveries).
send
Sends m from the store home at now: refused when every reader would drop it or its sender’s window to the recipient is full (window_for; a steer is never paced: a pause is answered by a resume). The write keeps the log bounded (bound). A steer from this node is admitted first, as Role::Local (steer.rs), so a reader that sees its line sees it count.
sender
The sender: from, else the calling session (caller), else the engineer.
sender_label
The sender of m as a label names it: the name it gave, else the start of its session id.
short_node
A node key as a label shows it: its first NODE_CHARS characters (every label of a sender’s node: a delivered line, steer.rs who, borg inbox --show).
short_session
A session id as a label shows it for a sender that gave no name: its first SESSION_CHARS.
steer_right
Whether a steer from me counts on another node: under the role the held membership gives it, admin or steer (steer.rs Role::of_member), as each receiver checks at admission. The document is read unverified: the mesh verified it when it saved it, and every receiver checks again, so this only spares the sender a false report.
talk_mark
The talk of the store home’s log (talk), for a reader that polls it (listen.rs): None while there is no log.
unread
How many of msgs (as read gives them) are for session of this node here (started at started) and not shown to it yet: what its next prompts or tool calls would show.
window_for
The window of by’s tells and asks to to (written as a line writes it) in lines at now.
within_windows
The ids of the tells and asks of lines within what every window admits (window_for): each one that a recipient acknowledged, and each that, with the sender’s later messages to the same recipient stamped within V1_RATE_MS of it, makes at most WINDOW_CAP unacknowledged ones.
wrote
Records a write of the log at p under its lock (every writer: send, ack, borg-mesh sync.rs store_messages): before, the log’s mark before it (mark_of; None: no log); change, what it did to the log; talk, whether it wrote a tell, ask or steer. The generation stays only for Seen lines appended to the log as the record left it, or added by a rewrite that removed only lines past the TTL (Change::Expired), with nothing else written meanwhile (the length says so); anything else moves it, to at least now in ns, so a record made anew never repeats one a reader holds. Best effort: a record that is not the log’s makes talk fall back to the log’s mark.