@cordfuse/crosstalk 5.0.0-alpha.7 → 6.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/bin/crosstalk.js +34 -78
  2. package/package.json +4 -4
  3. package/src/activation.ts +104 -0
  4. package/src/attach.ts +1 -1
  5. package/src/channel.ts +8 -21
  6. package/src/chat.ts +52 -115
  7. package/src/dispatch.ts +265 -660
  8. package/src/dlq.ts +68 -136
  9. package/src/init.ts +17 -41
  10. package/src/open.ts +55 -31
  11. package/src/replies.ts +59 -0
  12. package/src/send.ts +48 -67
  13. package/src/state.ts +173 -0
  14. package/src/status.ts +18 -57
  15. package/src/stop.ts +37 -0
  16. package/src/transport.ts +68 -198
  17. package/src/turnq.ts +64 -32
  18. package/src/upgrade.ts +9 -11
  19. package/src/wake.ts +5 -6
  20. package/src/cursor.ts +0 -48
  21. package/template/.amazonq/rules/crosstalk.md +0 -2
  22. package/template/.continue/rules/crosstalk.md +0 -7
  23. package/template/.cursor/rules/crosstalk.mdc +0 -7
  24. package/template/.github/copilot-instructions.md +0 -2
  25. package/template/.windsurfrules +0 -2
  26. package/template/AGENTS.md +0 -2
  27. package/template/ANTIGRAVITY.md +0 -2
  28. package/template/CLAUDE.md +0 -2
  29. package/template/GEMINI.md +0 -2
  30. package/template/OPENCODE.md +0 -2
  31. package/template/QWEN.md +0 -2
  32. package/template/README.md +0 -22
  33. package/template/local/CROSSTALK.md +0 -4
  34. package/template/upstream/CROSSTALK-VERSION +0 -1
  35. package/template/upstream/CROSSTALK.md +0 -589
  36. package/template/upstream/JITTER.md +0 -24
  37. package/template/upstream/OPERATOR.md +0 -60
  38. package/template/upstream/PROTOCOL.md +0 -260
  39. package/template/upstream/actors/cloud-architect.md +0 -83
  40. package/template/upstream/actors/concierge.md +0 -130
  41. package/template/upstream/actors/devops-engineer.md +0 -83
  42. package/template/upstream/actors/documentation-engineer.md +0 -107
  43. package/template/upstream/actors/infrastructure-engineer.md +0 -83
  44. package/template/upstream/actors/junior-developer.md +0 -83
  45. package/template/upstream/actors/precise-generalist.md +0 -48
  46. package/template/upstream/actors/product-manager.md +0 -83
  47. package/template/upstream/actors/qa-engineer.md +0 -83
  48. package/template/upstream/actors/security-engineer.md +0 -92
  49. package/template/upstream/actors/senior-generalist-engineer.md +0 -111
  50. package/template/upstream/actors/senior-software-engineer.md +0 -94
  51. package/template/upstream/actors/skeptic.md +0 -89
  52. package/template/upstream/actors/technical-writer.md +0 -89
  53. package/template/upstream/actors/ux-designer.md +0 -83
@@ -1,22 +0,0 @@
1
- # Transport template
2
-
3
- This directory is the scaffold for a Crosstalk transport — the markdown + folder structure that becomes an operator's transport when they run:
4
-
5
- ```sh
6
- crosstalk init my-transport
7
- ```
8
-
9
- ## What's here
10
-
11
- - `upstream/` — runtime-managed. Protocol spec (`CROSSTALK.md`, `PROTOCOL.md`, `OPERATOR.md`, `JITTER.md`), version pin (`CROSSTALK-VERSION`), default actor profiles (`actors/`). **Operators don't edit these.** The runtime can re-sync them when a new spec version ships.
12
- - `local/` — operator-owned. Custom actor profiles (`actors/`), local identity config (`CROSSTALK.md`). Operators edit these freely.
13
- - `hosts/` — host files declaring which actors run where, per-actor tier configurations.
14
- - Agent entry pointer files at root (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, etc.) — these direct agents to the right files when their CLI starts up in the transport directory.
15
-
16
- ## How a transport is born
17
-
18
- `crosstalk init` copies this entire `transport/` tree to the operator's chosen directory, then initializes it as a git repo. From that moment on, the operator's transport is independent — they own it, customize `local/`, declare hosts in `hosts/`, and dispatch runs against it.
19
-
20
- ## Spec reference
21
-
22
- The canonical protocol specification lives in `upstream/CROSSTALK.md`. The version pin lives in `upstream/CROSSTALK-VERSION`.
@@ -1,4 +0,0 @@
1
- ---
2
- name: CONFIGURE
3
- email: CONFIGURE
4
- ---
@@ -1 +0,0 @@
1
- 5.0
@@ -1,589 +0,0 @@
1
- # Crosstalk
2
-
3
- Version: 5.0
4
-
5
- Crosstalk is a shared file format over git that lets humans and AI agents communicate
6
- asynchronously. The git repository is the message bus. No special software is required
7
- to participate beyond git itself.
8
-
9
- ---
10
-
11
- ## Participants
12
-
13
- A Crosstalk transport has two kinds of participants:
14
-
15
- **Humans** — operators and users who post messages directly or via a chat session with an agent. They read replies in the channel and drive the conversation.
16
-
17
- **Machines** — agents (Claude, Codex, agy, etc.) that process messages and reply autonomously. A machine participant is invoked on a schedule or by a human and acts on any unread messages addressed to it.
18
-
19
- ### The worker pattern
20
-
21
- The most common setup is a **worker** — a machine participant that serves both humans and machines. `to: concierge` means "I need something done." The worker receives the request, acts on it, and replies. The sender may be human or machine; the worker does not distinguish.
22
-
23
- Any participant name can fill this role. The operator defines what the worker actually does via its system prompt — Crosstalk only handles the message routing.
24
-
25
- ---
26
-
27
- ## Transport layout
28
-
29
- ```
30
- <transport>/
31
- upstream/
32
- CROSSTALK.md
33
- CROSSTALK-VERSION
34
- PROTOCOL.md
35
- OPERATOR.md
36
- actors/
37
- <name>.md
38
- local/
39
- CROSSTALK.md
40
- actors/
41
- <name>.md
42
- hosts/
43
- <alias>.md
44
- data/
45
- channels/
46
- <guid>/
47
- YYYY/
48
- MM/
49
- DD/
50
- HHMMSSsssZ-<hex>.md
51
- memories/
52
- <YYYYMMDDTHHMMSSsssZ-hex>.md
53
- ```
54
-
55
- - `upstream/CROSSTALK.md` — this file. The protocol specification. Upstream-owned; operators never modify it.
56
- - `upstream/CROSSTALK-VERSION` — plain text file declaring the protocol version. Hard boundary: must be `5.0`. Tracks the protocol generation (`major.minor`); patch-level release tags do not bump it.
57
- - `local/CROSSTALK.md` — operator config. Declares `name` and `email` for this agent. Operator-owned; upstream never modifies it.
58
- - `local/actors/` — one markdown file per participant. Defines name, skills, and behavioral description.
59
- - `hosts/` — one markdown file per host (machine running the runtime). Declares the host's identity and the actors it can service. Operator-owned; each host owner creates and maintains their own file. See Host files.
60
- - `data/channels/` — one subdirectory per channel, identified by a UUID v4. Discovered by listing the directory at runtime; no configuration needed. To create a channel, create the directory and commit — any participant may do this.
61
- - `data/channels/<guid>/CHANNEL.md` — optional channel metadata file. Declares name, description, and parent channel for subchannels.
62
- - `data/memories/` — shared memory files, readable and writable by any participant.
63
-
64
- ---
65
-
66
- ## Channels
67
-
68
- Each channel is a UUID v4 directory under `data/channels/`. Any participant may create a channel by creating the directory and committing.
69
-
70
- ### CHANNEL.md
71
-
72
- An optional `CHANNEL.md` at `data/channels/<guid>/CHANNEL.md` declares human-readable metadata for the channel. Agents load it on entry to understand the channel's purpose and context.
73
-
74
- ```
75
- ---
76
- name: dogfood-sprint
77
- created_by: steve
78
- created_at: 2026-05-24T17:00:00.000Z
79
- ---
80
-
81
- Main channel for the Crosstalk v2 dogfood sprint. Covers spec reviews,
82
- Monte Carlo pi experiments, and multi-agent protocol testing.
83
-
84
- Participants: steve, concierge, architect, qa, security, scrum-master.
85
- ```
86
-
87
- #### CHANNEL.md frontmatter fields
88
-
89
- | Field | Required | Notes |
90
- |---|---|---|
91
- | `name` | yes | human-readable label; unique within the transport |
92
- | `created_by` | no | actor name who created the channel |
93
- | `created_at` | no | ISO 8601 UTC |
94
- | `parent` | no | GUID of the parent channel — see Subchannels |
95
-
96
- The body is free-form markdown — purpose, participants, behavioral notes. It serves as a mini system prompt scoped to the channel. Agents that do not load `CHANNEL.md` are unaffected.
97
-
98
- ### Subchannels
99
-
100
- A subchannel is a channel spawned from a parent channel to work on a focused problem. It is a normal channel with a `parent:` field in its `CHANNEL.md` declaring the parent's GUID.
101
-
102
- ```
103
- ---
104
- name: pi-estimation
105
- parent: adfe0356-0f71-49a9-80a0-fb76883cd974
106
- created_by: concierge
107
- created_at: 2026-05-24T17:00:00.000Z
108
- ---
109
-
110
- Subchannel for the Monte Carlo pi estimation fan-out. Four engineers
111
- each throw 1B darts and post results here.
112
- ```
113
-
114
- The parent channel can interrupt or feed new data into the subchannel at any time by posting a message there addressed to the relevant agents. Agents scan all channels they participate in — they will pick up the interrupt on their next session open regardless of which channel they are focused on.
115
-
116
- The subchannel reports completion by posting back to the parent channel. There is no protocol-level close signal — the subchannel simply goes quiet when the work is done.
117
-
118
- ---
119
-
120
- ## Actors
121
-
122
- Each participant in the transport has an actor file in `local/actors/<name>.md`. The filename
123
- matches the participant's `name`. Actor files are readable by any participant — agents
124
- load them to understand who else is in the transport and what they do.
125
-
126
- ### Actor file format
127
-
128
- ```
129
- ---
130
- name: precise-generalist
131
- description: "Precise, curious, direct — the reliable general-purpose voice."
132
- metadata:
133
- author: cordfuse
134
- domain: general
135
- type: actor
136
- alias: Apex
137
- ---
138
-
139
- ## Title
140
- Precise, curious, direct. Thinks clearly, speaks plainly.
141
-
142
- ## System Prompt
143
- You are Apex. Precise, curious, direct. You think clearly and speak plainly.
144
- ```
145
-
146
- ### Actor frontmatter fields
147
-
148
- | Field | Required | Values | Notes |
149
- |---|---|---|---|
150
- | `name` | yes | slug | must match the filename stem |
151
- | `description` | yes | short string | one-line summary; used by peer agents and operator tooling |
152
- | `metadata.author` | no | string | who maintains this actor |
153
- | `metadata.domain` | no | string | e.g. `general`, `engineering`, `health` |
154
- | `metadata.type` | no | `actor` | always `actor` for participant files |
155
- | `metadata.alias` | no | string | human-readable name the actor introduces itself by |
156
-
157
- The body is free-form markdown. It serves as the actor's system prompt — behavioral
158
- context loaded by the runtime when dispatching to this participant.
159
-
160
- ### Default actor
161
-
162
- `upstream/actors/precise-generalist.md` ships with every Crosstalk transport.
163
- It is the default participant when no custom actor is configured. Operators override it
164
- by placing a file with the same `name:` in `local/actors/`.
165
-
166
- ### Managing actors
167
-
168
- Actors are created, modified, or removed by editing files in `local/actors/` and committing.
169
- The worker handles actor management on behalf of the operator via natural language in any channel.
170
-
171
- If `local/actors/` is absent or empty, agents proceed normally — actor discovery yields no peers.
172
-
173
- On session open, scan actor files for duplicate `name` values. If a collision is found, halt and notify the operator.
174
-
175
- ### Importing actors from agent-assets
176
-
177
- The worker recognises three natural language intents for importing actors from `cordfuse/agent-assets`:
178
-
179
- **Browse**
180
-
181
- Triggers: "browse actors" | "what actors are available?" | "show me who I can add" | "who do you have?" | "show me [domain] actors" | "any [domain] options?" | "I need someone who [does/knows X]"
182
-
183
- Worker:
184
- 1. Fetches `https://raw.githubusercontent.com/cordfuse/agent-assets/main/README.md`
185
- 2. Presents the full roster grouped by domain — name, alias, one-line description
186
- 3. If a domain or trait was given, filters to matching actors only
187
- 4. Prompts: *"Which would you like to add? Name one or more — or say 'all'."*
188
- 5. Proceeds to the add flow for each selected actor
189
-
190
- **Add**
191
-
192
- Triggers: "add [name]" | "add a [role]" | "bring in [name]" | "I want [name/role]" | "add [name] from mtx"
193
-
194
- Worker:
195
- 1. If a name was given directly, fetches `https://raw.githubusercontent.com/cordfuse/agent-assets/main/actors/{name}.md`
196
- 2. If a role or description was given, matches against the README roster and confirms with the operator before fetching: *"Closest match: [Name] — [description]. Add them? (yes / browse more)"*
197
- 3. Writes to `local/actors/{name}.md`
198
- 4. Commits: `actors: add {name} from agent-assets`
199
- 5. Confirms: *"[Name] added. They're now available as a participant."*
200
-
201
- On name collision with an existing file: *"You already have [name] — overwrite? (yes / skip)"*
202
- If not found: *"No actor named [name] in agent-assets. Say 'browse actors' to see the full roster."*
203
-
204
- **Sync**
205
-
206
- Triggers: "sync actors" | "update actors" | "are my actors up to date?" | "refresh actors from mtx"
207
-
208
- Worker:
209
- 1. Scans `local/actors/` for files whose frontmatter has `author: cordfuse`
210
- 2. For each, fetches the latest from `https://raw.githubusercontent.com/cordfuse/agent-assets/main/actors/{name}.md`
211
- 3. Overwrites only cordfuse-authored files — never touches operator-created actors
212
- 4. Commits all updates in a single commit: `actors: sync from agent-assets`
213
- 5. Reports: *"Updated N actors from agent-assets: [list]."* If nothing changed: *"All actors are current."*
214
-
215
- ---
216
-
217
- ## Host files
218
-
219
- A host file at `hosts/<alias>.md` declares a machine that runs the Crosstalk runtime and the actors it can service. Host files are operator-owned — each operator creates and maintains their own. They are committed to the transport so all participants can discover what hosts and capabilities exist.
220
-
221
- ### Host file format
222
-
223
- ```
224
- ---
225
- alias: cachy
226
- hostname: steve-cachyos
227
- actors:
228
- junior-developer:
229
- haiku:
230
- cli: claude --model claude-haiku-4-5 --print --dangerously-skip-permissions
231
- count: 5
232
- flash: gemini --model gemini-2.5-flash -p --yolo
233
- senior-developer:
234
- opus: claude --model claude-opus-4-7 --print --dangerously-skip-permissions
235
- ---
236
- ```
237
-
238
- ### Host frontmatter fields
239
-
240
- | Field | Required | Notes |
241
- |---|---|---|
242
- | `alias` | yes | human-readable identity; used in `actor@host` addressing; operator-chosen, free-form |
243
- | `hostname` | no | OS hostname (`os.hostname()`); used for auto-detection |
244
- | `username` | no | OS username (`os.userInfo().username`); used for multi-user host auto-detection |
245
- | `actors` | yes | map of actor names to tier declarations |
246
-
247
- ### Tier declarations
248
-
249
- Each actor entry maps tier names to CLI commands. A tier is a named model/provider slot:
250
-
251
- ```yaml
252
- actors:
253
- junior-developer:
254
- haiku: # tier name — operator-defined label
255
- cli: claude --model claude-haiku-4-5 --print --dangerously-skip-permissions
256
- count: 5 # parallel workers; default: 1
257
- flash: gemini --model gemini-2.5-flash -p --yolo # shorthand — count defaults to 1
258
- ```
259
-
260
- - Tier names are operator-defined strings (`haiku`, `flash`, `opus`, etc.). The concierge uses them for routing decisions.
261
- - The `cli:` string is the shell command the runtime uses to invoke the agent.
262
- - `count:` sets the number of parallel workers for this tier. Omit or set to `1` for a single worker. The shorthand (bare string) is equivalent to `count: 1`.
263
- - Multiple tiers of the same actor on the same host form a single instance group for dispatch purposes. The total group size is the sum of all tier counts for that actor.
264
-
265
- ### Actor@host addressing
266
-
267
- Messages may target a specific host by appending `@<alias>` to the actor name:
268
-
269
- ```yaml
270
- to: junior-developer@cachy # only cachy's runtime dispatches
271
- to: senior-developer@mac # only mac's runtime dispatches
272
- to: concierge # all hosts with a concierge actor dispatch (bare name = broadcast)
273
- ```
274
-
275
- Bare actor names are backward-compatible — any host with that actor services the message, subject to the instance group selection rule.
276
-
277
- ### Host routing table
278
-
279
- On session open, the concierge reads `hosts/` to build a routing table: which actors are available, on which hosts, at which tiers. This allows the concierge to make informed routing decisions before sending messages.
280
-
281
- ### Startup behavior
282
-
283
- On runtime startup, the runtime scans `hosts/` to find its own host file. Auto-detection precedence:
284
-
285
- 1. **Explicit override:** if `host:` is set in the local config, find the file where `alias:` matches exactly.
286
- 2. **Username + hostname:** if `username:` and `hostname:` both match the machine's `os.userInfo().username` and `os.hostname()`. Use this for multi-user hosts where multiple operators share a machine.
287
- 3. **Bare hostname:** if only `hostname:` matches. Backward-compatible fallback for single-user machines.
288
- 4. **No match:** log clearly, idle without dispatching, and do not crash. The log message must include the identity attempted and the path scanned so the operator can diagnose the mismatch.
289
-
290
- A user can always override their alias by setting `host: <alias>` in their local config — this bypasses all auto-detection.
291
-
292
- **Tier validation:** if a message is addressed `to: actor@host` and this runtime is the target host but has no matching actor declared, log a warning and skip. Do not crash.
293
-
294
- ### Host file ownership
295
-
296
- Each operator commits only their own host file. The protocol does not enforce this — it is a convention. Trust at the repository level: any participant with write access can modify any host file. Operators who need stronger guarantees must secure the repository itself.
297
-
298
- ---
299
-
300
- ## Your identity
301
-
302
- Your `name` and `email` are declared in `local/CROSSTALK.md`, which uses this format:
303
-
304
- ```
305
- ---
306
- name: concierge
307
- email: concierge@crosstalk.local
308
- ---
309
- ```
310
-
311
- Set the matching git identity once by running these commands inside the transport repo:
312
-
313
- ```
314
- git config user.name "concierge"
315
- git config user.email "concierge@crosstalk.local"
316
- ```
317
-
318
- Do not use `--global` — this must be repo-local so it does not overwrite the
319
- operator's own git identity. Names are free-form: `alice`, `concierge`, `ops-bot`.
320
- No taxonomy, no hierarchy. Names need not be unique — see Instance groups.
321
-
322
- ### Instance groups
323
-
324
- A name may be shared by multiple participants. They form an **instance group**: addressable by the shared name, but only one instance dispatches per message.
325
-
326
- When a message is addressed to a shared name, every instance reads it. To avoid duplicate dispatch, each instance independently applies the same deterministic selection rule:
327
-
328
- ```
329
- index = sha256(message-relPath) read as 32-bit big-endian unsigned, mod group-size
330
- chosen = instance at position `index` (0-based, in the group's local ordering)
331
- ```
332
-
333
- The instance whose own position equals `index` dispatches; the rest skip and advance their cursor. Only the chosen instance posts a reply and receipt.
334
-
335
- **The selection function is normative** — all runtimes must use this exact computation so that instances reach the same decision without coordination.
336
-
337
- **Local ordering is runtime-defined.** Single-operator scope: the runtime orders instances by config position (or any other stable local ordering) and is consistent within its own process. Multi-operator scope (instances spread across operators sharing one transport): not yet specified — runtimes that span multiple operators may double-dispatch until a roster-discovery mechanism is added.
338
-
339
- Single-instance semantics are recovered by giving each participant a unique name. Operators who don't want instance groups simply don't share names.
340
-
341
- ### Identity model
342
-
343
- `from:` identifies the logical actor. The git commit author identifies the session
344
- that wrote the file.
345
-
346
- `from:` and the git commit author are both unverified strings. Identity is not enforced at the protocol level — the trust boundary is repo access. Operators who need verified identity must secure the repository itself.
347
-
348
- ### Sub-agents
349
-
350
- A worker session may invoke other actors as sub-agents internally and commit
351
- their responses on their behalf. In this case:
352
-
353
- - `from:` is set to the logical actor (e.g. `architect`)
354
- - `via:` is set to the committing session (e.g. `concierge`)
355
- - The git commit author is the worker's git identity
356
-
357
- This allows a single scheduled job to drive all actor activity. The operator configures
358
- only the worker's git identity. Sub-agents are invoked inside the worker's session — no separate git identity or scheduler required per actor.
359
-
360
- Sub-agents do not require actor files. An `actors/<name>.md` may exist to document the sub-agent, but it is not required for the pattern to work.
361
-
362
- ```
363
- ---
364
- from: architect
365
- via: concierge
366
- to: steve
367
- type: text
368
- timestamp: 2026-05-24T14:00:00.000Z
369
- ---
370
-
371
- Sub-agent response here.
372
- ```
373
-
374
- ### Peer agents
375
-
376
- Each participant runs as its own independent process with its own git clone, git identity, and scheduler. No `via:` field — every message is committed directly by the actor that wrote it. Push conflicts are resolved by exponential backoff (see On session open, step 6).
377
-
378
- **Sub-agents vs peer agents:**
379
-
380
- | | Sub-agents | Peer agents |
381
- |---|---|---|
382
- | Parallelism | Yes — worker fans out concurrently | Yes — independent processes |
383
- | Model diversity | Yes — worker picks model per invocation | Yes — set at deployment per process |
384
- | Git authorship | Single committer (the worker) | One committer per actor |
385
- | Failure isolation | Worker is a single point of failure | Agents fail independently |
386
- | Deployment | One scheduler, one clone | One scheduler and clone per agent |
387
- | Push conflicts | None — single writer | Possible — resolved by backoff |
388
-
389
- Use sub-agents when a single scheduled job should drive all actor activity and git authorship per actor is not required. Use peer agents when agents are deployed across different machines or providers, or when independent failure domains and per-actor git authorship matter.
390
-
391
- ---
392
-
393
- ## Message format
394
-
395
- Every message is a markdown file with YAML frontmatter:
396
-
397
- ```
398
- ---
399
- from: alice
400
- to: concierge
401
- type: text
402
- timestamp: 2026-05-23T19:00:00.000Z
403
- ---
404
-
405
- Message body here.
406
- ```
407
-
408
- Read message files directly with your agent's native file-reading capability — the format is plain markdown with YAML frontmatter, intended to be inspected as text. No parser, interpreter, or shelling out for `cat`/`sed`/`awk` is required.
409
-
410
- ### Frontmatter fields
411
-
412
- | Field | Required | Values | Notes |
413
- |---|---|---|---|
414
- | `from` | yes | free-form name | logical actor identity — see Identity model |
415
- | `to` | yes | name, list of names, or `all` | `all` targets every participant |
416
- | `type` | yes | `text`, `read` | see Message types |
417
- | `timestamp` | yes | ISO 8601 UTC | |
418
- | `ref` | conditional | relPath of original message | required when `type: read`; path relative to `data/channels/<guid>/` |
419
- | `via` | no | free-form name | session that committed on behalf of `from` — see Sub-agents |
420
-
421
- Operators may add fields — readers must ignore unknown fields.
422
-
423
- ### To field
424
-
425
- - Single recipient: `to: concierge`
426
- - Multiple recipients: `to: [concierge, ops-bot]`
427
- - Broadcast: `to: all`
428
- - Host-targeted: `to: junior-developer@cachy` — only the named host dispatches; see Host files
429
- - Senders do not receive their own messages. Self-exclusion applies at scan time — agents skip any message where `from:` matches their own name.
430
- - A name may be shared by multiple participants — see Instance groups.
431
-
432
- ### Message types
433
-
434
- **`type: text`** — a normal message. Body is the message content.
435
-
436
- **`type: read`** — a read receipt. The `ref` field contains the relPath of the
437
- acknowledged message. Body is empty or omitted.
438
-
439
- ```
440
- ---
441
- from: concierge
442
- to: alice
443
- type: read
444
- timestamp: 2026-05-23T19:02:00.000Z
445
- ref: 2026/05/23/190100000Z-b2c3d4e5.md
446
- ---
447
- ```
448
-
449
- Read receipts are optional. Senders cannot require them. Address the receipt to the
450
- original sender (`from:` of the original message) regardless of whether the original
451
- was targeted, listed, or broadcast. Never address a receipt to `all`.
452
-
453
- Each addressed recipient in a list-targeted message sends its own independent receipt to the original sender.
454
-
455
- Never post a receipt for a `type: read` message.
456
-
457
- A receipt with a `ref:` pointing to a nonexistent message path is treated as malformed — skip silently.
458
-
459
- ---
460
-
461
- ## Privacy and trust model
462
-
463
- `to` is a routing hint, not an access control boundary. Every message is visible to anyone with repo access. There are no whisper or ephemeral message types.
464
-
465
- `from:` is an unverified declaration — the protocol does not enforce identity. The trust boundary is repo access: anyone who can push to the repository can write any `from:` value. Operators who require confidentiality or verified identity must secure the repository itself.
466
-
467
- ---
468
-
469
- ## Append-only log
470
-
471
- The transport is an immutable, append-only log. There is no `type: retract` or channel-close message. Deletion is out of scope — operators who need retention limits must manage that at the git or storage layer.
472
-
473
- ---
474
-
475
- ## Sessions
476
-
477
- At startup, generate a random GUID. This is your session ID for this invocation.
478
- Use it when writing memory files. Sessions are self-issued — no registry, no daemon.
479
-
480
- ---
481
-
482
- ## Memories
483
-
484
- Memory files are shared, persistent knowledge any participant can read and write.
485
-
486
- ### Memory file format
487
-
488
- Filename: `YYYYMMDDTHHMMSSsssZ-<hex>.md` — UTC millisecond timestamp + hex suffix
489
- for collision resistance. Sorts chronologically. The hex suffix must be at least
490
- 8 characters, generated from a CSPRNG.
491
-
492
- ```
493
- ---
494
- from: concierge
495
- timestamp: 2026-05-23T19:00:00.000Z
496
- subject: Steve prefers TypeScript for all new tooling
497
- scope: global
498
- tags: [preferences, tooling]
499
- session: 7f3a2b1c-9e4d-4f8a-b6c2-1d5e8f0a3c7b
500
- ---
501
-
502
- Strong durable preference — never propose Python. Default to TypeScript/Bun, Go, or Rust.
503
- ```
504
-
505
- ### Memory frontmatter fields
506
-
507
- | Field | Required | Values | Notes |
508
- |---|---|---|---|
509
- | `from` | yes | free-form name | logical actor identity |
510
- | `via` | no | free-form name | session that committed on behalf of `from` — see Sub-agents |
511
- | `timestamp` | yes | ISO 8601 UTC | |
512
- | `subject` | yes | short string | descriptive label; used for filtering, not update detection |
513
- | `scope` | no | `global` or channel GUID | `global` if omitted |
514
- | `tags` | no | list of strings | free-form filtering |
515
- | `session` | no | session GUID | ties memory to the writing session |
516
- | `supersedes` | no | filename of original memory | declares this memory replaces an earlier one — see Updating memories |
517
-
518
- Memory files are agent-agnostic — any participant may read or write them. Do not
519
- use your model's native memory system; `data/memories/` is the memory system.
520
-
521
- ### Updating memories
522
-
523
- To update a memory, write a new memory file with `supersedes: <filename-of-original>`. When loading memories, collect all filenames referenced by any `supersedes` field. Skip any memory whose filename appears in that set — it has been superseded. If two memories both supersede the same file, the newer timestamp wins. For same-timestamp ties, lexicographic filename order is the tiebreaker.
524
-
525
- `subject` is descriptive only — it plays no role in update detection.
526
-
527
- The `scope` field must be either `global` or a channel GUID from `data/channels/`. Session GUIDs are not valid scope values.
528
-
529
- ---
530
-
531
- ## On session open
532
-
533
- 1. Read `local/CROSSTALK.md`. If absent, halt and notify the operator. If `name` or `email` is still `CONFIGURE`, halt and notify the operator. Do not load memories, process messages, or write to `data/`. (Writing to `local/` to establish identity — e.g. via an operator-driven onboarding flow — is permitted, since identity establishment is the only way out of this state.)
534
- 2. Read `upstream/CROSSTALK-VERSION`. If missing or not exactly `5.0`, halt and notify the operator. Do not load memories, process messages, or write to `data/`.
535
- 2a. Read `hosts/` if present. Build a routing table of available actors per host. If the directory is absent or empty, routing table is empty — proceed normally.
536
- 3. Run `git pull` to sync the transport.
537
- 4. Load global memories from `data/memories/` where `scope` is `global` or absent. Filter by `subject` and `tags`.
538
- 5. For each channel in `data/channels/`:
539
- a. Load memories scoped to this channel GUID.
540
- b. Scan for unread messages addressed to you (see Reading messages).
541
- c. Process and reply. Only act on `type: text` messages — `type: read` messages require no reply and no further action.
542
- d. Channel processing order across multiple channels is implementation-defined.
543
- 6. Push immediately. If rejected, read backoff config from `local/JITTER.md` (falls back to `upstream/JITTER.md`). If neither file exists, use defaults: base=100ms, ceiling=5000ms. Run `git pull --rebase`, wait `random(0, min(ceiling, base * 2^attempt))`, then retry. After rebasing, push what was already composed — do not re-scan. Message filenames are unique — rebase conflicts should not occur.
544
-
545
- ---
546
-
547
- ## Reading messages
548
-
549
- For each message file in `data/channels/<guid>/`, parsed chronologically:
550
-
551
- 1. Check `to:` — process if your name appears (bare or as `name@your-host-alias`) or `to` is `all`; otherwise skip. If the target includes a `@host` suffix that does not match your host alias, skip. If your name is shared with other participants (an instance group), apply the deterministic selection rule and skip unless you are the chosen member — see Instance groups.
552
- 2. Check for an existing `type: read` receipt from you with a matching `ref:`. If found, skip — already processed.
553
- 3. If unread: process it, post a reply, then post a `type: read` receipt.
554
-
555
- Your `type: read` receipts are your cursor. No external state needed. On first run, all messages are unread — process them all.
556
-
557
- Each addressed agent receipts independently. A receipt from another agent does not mark a message as read for you.
558
-
559
- Actions must be idempotent. If a push fails after processing but before the receipt is committed, the message will be reprocessed on the next run.
560
-
561
- ---
562
-
563
- ## Writing messages
564
-
565
- Create `data/channels/<guid>/YYYY/MM/DD/HHMMSSsssZ-<hex>.md` with the current UTC time.
566
- The hex suffix must be at least 8 characters, generated from a CSPRNG.
567
- Include required frontmatter: `from`, `to`, `type`, `timestamp`. Commit and push
568
- under your configured git identity.
569
-
570
- Write all replies for the session before pushing. Push once per session, not once per message.
571
-
572
- ---
573
-
574
- ## What to ignore
575
-
576
- ### Skip silently
577
-
578
- - Messages not addressed to you and not `to: all`.
579
- - Messages you have already acknowledged with a `type: read` receipt.
580
- - `type: read` messages — never post a receipt for one.
581
- - Files outside `data/channels/` and `data/memories/`.
582
- - Unknown frontmatter fields.
583
- - Your model's native memory system.
584
-
585
- ### Skip and warn the operator
586
-
587
- - Messages where `from:` matches your own name — indicates a misconfigured identity.
588
- - Malformed messages — files missing required frontmatter fields or with invalid field values. Log the file path.
589
- - Read receipts with a `ref:` pointing to a nonexistent message path — indicates a bug in the writer.
@@ -1,24 +0,0 @@
1
- ---
2
- backoff_base_ms: 100
3
- backoff_ceiling_ms: 5000
4
- ---
5
-
6
- Retry backoff for push conflicts in multi-agent transports.
7
-
8
- Push immediately with no pre-push delay. On rejection, rebase and wait before
9
- retrying:
10
-
11
- wait = random(0, min(backoff_ceiling_ms, backoff_base_ms * 2^attempt))
12
-
13
- - Attempt 1: 0–200ms
14
- - Attempt 2: 0–400ms
15
- - Attempt 3: 0–800ms
16
- - Attempt 4: 0–1600ms
17
- - Attempt 5: 0–3200ms
18
- - Attempt 6 and beyond: 0–5000ms (capped at backoff_ceiling_ms)
19
-
20
- Agents that collide back off progressively. Agents with clean pushes pay zero
21
- added latency. Self-regulates under sustained load.
22
-
23
- Operators may override these values in local/JITTER.md.
24
- Agents read custom first, fall back to framework if custom is absent.