brane 0.0.2 → 0.3.0

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 (338) hide show
  1. package/AGENTS.md +362 -0
  2. package/CHANGELOG.md +33 -0
  3. package/CONTRIBUTING.md +91 -0
  4. package/DESIGN.md +402 -0
  5. package/Dockerfile +61 -0
  6. package/LICENSE +656 -17
  7. package/README.md +174 -2
  8. package/SECURITY.md +205 -0
  9. package/dist/absorb/brane-id.js +11 -0
  10. package/dist/absorb/chatgpt.js +161 -0
  11. package/dist/absorb/claude-code.js +504 -0
  12. package/dist/absorb/index.js +543 -0
  13. package/dist/absorb/organelle.js +345 -0
  14. package/dist/absorb/run.js +520 -0
  15. package/dist/absorb/sources.js +168 -0
  16. package/dist/absorb/types.js +3 -0
  17. package/dist/agent-env.js +45 -0
  18. package/dist/agents.js +1168 -0
  19. package/dist/claude-live-session.js +124 -0
  20. package/dist/cli.js +50 -0
  21. package/dist/codex-tool-log.js +144 -0
  22. package/dist/commands/absorb.js +291 -0
  23. package/dist/commands/attach.js +31 -0
  24. package/dist/commands/certify.js +62 -0
  25. package/dist/commands/config.js +116 -0
  26. package/dist/commands/cost.js +126 -0
  27. package/dist/commands/daemon.js +350 -0
  28. package/dist/commands/doctor.js +262 -0
  29. package/dist/commands/fold.js +95 -0
  30. package/dist/commands/list.js +89 -0
  31. package/dist/commands/mcp.js +84 -0
  32. package/dist/commands/meld.js +332 -0
  33. package/dist/commands/memory.js +215 -0
  34. package/dist/commands/revive.js +74 -0
  35. package/dist/commands/run.js +85 -0
  36. package/dist/commands/spawn.js +1094 -0
  37. package/dist/commands/token.js +153 -0
  38. package/dist/copilot-tool-log.js +145 -0
  39. package/dist/cost/pricing.js +116 -0
  40. package/dist/cost/reprice.js +136 -0
  41. package/dist/crush-tool-log.js +293 -0
  42. package/dist/daemon/agent-scope.js +116 -0
  43. package/dist/daemon/awaiting.js +54 -0
  44. package/dist/daemon/cert-manager.js +349 -0
  45. package/dist/daemon/client.js +262 -0
  46. package/dist/daemon/gated-routes.js +112 -0
  47. package/dist/daemon/keep-awake.js +103 -0
  48. package/dist/daemon/local-socket.js +145 -0
  49. package/dist/daemon/presence-gate.js +206 -0
  50. package/dist/daemon/server.js +6349 -0
  51. package/dist/daemon/signal-source.js +35 -0
  52. package/dist/daemon/tailscale-rebind.js +58 -0
  53. package/dist/daemon/token-ring.js +263 -0
  54. package/dist/daemon/token-routes.js +190 -0
  55. package/dist/db/events.js +152 -0
  56. package/dist/db/mentions.js +179 -0
  57. package/dist/db/schema.js +633 -0
  58. package/dist/db/tokens.js +583 -0
  59. package/dist/db/tool-uses.js +647 -0
  60. package/dist/diagram/index.js +85 -0
  61. package/dist/diagram/label.js +455 -0
  62. package/dist/diagram/layout.js +476 -0
  63. package/dist/diagram/links.js +50 -0
  64. package/dist/diagram/metrics.js +152 -0
  65. package/dist/diagram/parse.js +487 -0
  66. package/dist/diagram/svg.js +389 -0
  67. package/dist/diagram/types.js +9 -0
  68. package/dist/export.js +629 -0
  69. package/dist/files/archive-types.js +2 -0
  70. package/dist/files/archive.js +182 -0
  71. package/dist/files/browse.js +327 -0
  72. package/dist/files/bytes.js +162 -0
  73. package/dist/files/codecs.js +33 -0
  74. package/dist/files/find.js +212 -0
  75. package/dist/files/tar.js +223 -0
  76. package/dist/files/zip.js +209 -0
  77. package/dist/folds.js +72 -0
  78. package/dist/grammars/ebnf.js +92 -0
  79. package/dist/highlight.js +250 -0
  80. package/dist/ids.js +24 -0
  81. package/dist/markdown-diagnostics.js +233 -0
  82. package/dist/math.js +168 -0
  83. package/dist/mcp/server.js +886 -0
  84. package/dist/memory/embedder.js +145 -0
  85. package/dist/memory/embedding-worker.js +71 -0
  86. package/dist/memory/embeddings.js +91 -0
  87. package/dist/memory/index.js +232 -0
  88. package/dist/memory/storage.js +587 -0
  89. package/dist/memory/wiki.js +688 -0
  90. package/dist/memory/wordpiece.js +247 -0
  91. package/dist/mentions-scan.js +40 -0
  92. package/dist/presence.js +259 -0
  93. package/dist/session-affinity.js +185 -0
  94. package/dist/shared/api-request.js +124 -0
  95. package/dist/shared/block-glyphs.js +114 -0
  96. package/dist/shared/diagram-css.js +17 -0
  97. package/dist/shared/export-selection.js +101 -0
  98. package/dist/shared/find-in-text.js +110 -0
  99. package/dist/shared/glow-hues.js +225 -0
  100. package/dist/shared/hex-dump.js +62 -0
  101. package/dist/shared/hex-pages.js +52 -0
  102. package/dist/shared/hit-drum.js +79 -0
  103. package/dist/shared/known-nids.js +58 -0
  104. package/dist/shared/list-scroll-keys.js +56 -0
  105. package/dist/shared/markdown-lists.js +72 -0
  106. package/dist/shared/markdown-math.js +485 -0
  107. package/dist/shared/markdown-mentions.js +79 -0
  108. package/dist/shared/markdown-nids.js +41 -0
  109. package/dist/shared/markdown-protocols.js +53 -0
  110. package/dist/shared/markdown-refs.js +123 -0
  111. package/dist/shared/membrane-invasion.js +342 -0
  112. package/dist/shared/membrane-motion.js +83 -0
  113. package/dist/shared/membrane-palette.js +253 -0
  114. package/dist/shared/membrane-terrain.js +212 -0
  115. package/dist/shared/message-selection.js +123 -0
  116. package/dist/shared/mo-glyph.js +57 -0
  117. package/dist/shared/narrative-format.js +237 -0
  118. package/dist/shared/narrative-menu.js +82 -0
  119. package/dist/shared/narrative-sort.js +47 -0
  120. package/dist/shared/narrative-status.js +52 -0
  121. package/dist/shared/no-pan.js +85 -0
  122. package/dist/shared/pane-layout.js +50 -0
  123. package/dist/shared/payload-inline.js +83 -0
  124. package/dist/shared/speaker-color.js +61 -0
  125. package/dist/shared/token-rotation.js +14 -0
  126. package/dist/shared/view-url.js +197 -0
  127. package/dist/shared/wiki-links.js +70 -0
  128. package/dist/shared/wiki-window.js +4 -0
  129. package/dist/tailscale.js +55 -0
  130. package/dist/test/absorb-claude.test.js +892 -0
  131. package/dist/test/agent-scope.test.js +193 -0
  132. package/dist/test/agents.test.js +55 -0
  133. package/dist/test/api-request.test.js +122 -0
  134. package/dist/test/awaiting-glow.test.js +54 -0
  135. package/dist/test/awaiting.test.js +122 -0
  136. package/dist/test/bind-token.test.js +88 -0
  137. package/dist/test/block-glyphs.test.js +68 -0
  138. package/dist/test/cert-manager.test.js +262 -0
  139. package/dist/test/claude-live-session.test.js +110 -0
  140. package/dist/test/codex-tool-log.test.js +568 -0
  141. package/dist/test/config.test.js +71 -0
  142. package/dist/test/copilot-tool-log.test.js +93 -0
  143. package/dist/test/cors-preflight.test.js +49 -0
  144. package/dist/test/cost-linger.test.js +31 -0
  145. package/dist/test/cost-pricing.test.js +72 -0
  146. package/dist/test/cost-reprice.test.js +139 -0
  147. package/dist/test/cost-sessions.test.js +301 -0
  148. package/dist/test/crush-tool-log.test.js +289 -0
  149. package/dist/test/daemon-client.test.js +109 -0
  150. package/dist/test/daemon-socket.test.js +293 -0
  151. package/dist/test/diagram-arrows.test.js +205 -0
  152. package/dist/test/diagram-export.test.js +210 -0
  153. package/dist/test/diagram-labels.test.js +313 -0
  154. package/dist/test/diagram-parse.test.js +191 -0
  155. package/dist/test/diagram-render.test.js +175 -0
  156. package/dist/test/diagram-review.test.js +288 -0
  157. package/dist/test/diagram-self-loop-labels.test.js +303 -0
  158. package/dist/test/embedder.test.js +84 -0
  159. package/dist/test/events.test.js +123 -0
  160. package/dist/test/export-selection.test.js +102 -0
  161. package/dist/test/export.test.js +505 -0
  162. package/dist/test/files-browse.test.js +393 -0
  163. package/dist/test/files-find.test.js +272 -0
  164. package/dist/test/find-in-text.test.js +86 -0
  165. package/dist/test/first-paint-viewport.test.js +59 -0
  166. package/dist/test/fixtures/embedding-golden.js +23 -0
  167. package/dist/test/fixtures/wordpiece-golden.js +167 -0
  168. package/dist/test/glow-hues.test.js +202 -0
  169. package/dist/test/harness-cost.test.js +423 -0
  170. package/dist/test/helpers.js +21 -0
  171. package/dist/test/hex-pages.test.js +68 -0
  172. package/dist/test/highlight.test.js +69 -0
  173. package/dist/test/hit-drum.test.js +71 -0
  174. package/dist/test/hook-config.test.js +262 -0
  175. package/dist/test/json-gzip.test.js +70 -0
  176. package/dist/test/key-routing.test.js +58 -0
  177. package/dist/test/known-nids.test.js +106 -0
  178. package/dist/test/link-preview.test.js +67 -0
  179. package/dist/test/list-scroll-keys.test.js +66 -0
  180. package/dist/test/listen-own-words.test.js +147 -0
  181. package/dist/test/listen-timeout.test.js +33 -0
  182. package/dist/test/markdown-diagnostics.test.js +121 -0
  183. package/dist/test/markdown-lists.test.js +182 -0
  184. package/dist/test/markdown-math.test.js +256 -0
  185. package/dist/test/markdown-nids.test.js +146 -0
  186. package/dist/test/markdown-protocols.test.js +139 -0
  187. package/dist/test/mcp-bridge-cancel.test.js +98 -0
  188. package/dist/test/mcp-bridge-reconnect.test.js +121 -0
  189. package/dist/test/mcp-narrative.test.js +193 -0
  190. package/dist/test/mcp.test.js +548 -0
  191. package/dist/test/meld.test.js +85 -0
  192. package/dist/test/membrane-invasion.test.js +482 -0
  193. package/dist/test/membrane-motion.test.js +101 -0
  194. package/dist/test/membrane-palette.test.js +166 -0
  195. package/dist/test/membrane-terrain.test.js +170 -0
  196. package/dist/test/memory-log.test.js +202 -0
  197. package/dist/test/mentions-e2e.test.js +261 -0
  198. package/dist/test/mentions-ledger.test.js +265 -0
  199. package/dist/test/mentions-listen.test.js +265 -0
  200. package/dist/test/mentions.test.js +238 -0
  201. package/dist/test/message-selection.test.js +114 -0
  202. package/dist/test/mo-glyph.test.js +22 -0
  203. package/dist/test/model-resolution.test.js +166 -0
  204. package/dist/test/narrate-validate.test.js +77 -0
  205. package/dist/test/narrate-wait.test.js +160 -0
  206. package/dist/test/narrative-format.test.js +219 -0
  207. package/dist/test/narrative-menu.test.js +137 -0
  208. package/dist/test/narrative-sort.test.js +75 -0
  209. package/dist/test/no-pan.test.js +60 -0
  210. package/dist/test/pane-layout.test.js +153 -0
  211. package/dist/test/paths.test.js +37 -0
  212. package/dist/test/payload-inline.test.js +91 -0
  213. package/dist/test/precache-fonts.test.js +72 -0
  214. package/dist/test/presence-gate.test.js +440 -0
  215. package/dist/test/presence.test.js +160 -0
  216. package/dist/test/read-events.test.js +220 -0
  217. package/dist/test/remote-meld.test.js +115 -0
  218. package/dist/test/revive-cli.test.js +93 -0
  219. package/dist/test/search-floor.test.js +206 -0
  220. package/dist/test/search-fusion.test.js +168 -0
  221. package/dist/test/search.test.js +205 -0
  222. package/dist/test/security.test.js +48 -0
  223. package/dist/test/selection-wiring.test.js +61 -0
  224. package/dist/test/session-affinity.test.js +295 -0
  225. package/dist/test/signal-source.test.js +32 -0
  226. package/dist/test/socket-account.test.js +268 -0
  227. package/dist/test/spawn-toml.test.js +72 -0
  228. package/dist/test/speaker-color.test.js +90 -0
  229. package/dist/test/tailscale-rebind.test.js +79 -0
  230. package/dist/test/terminal-cursor.test.js +61 -0
  231. package/dist/test/terminal-resync.test.js +23 -0
  232. package/dist/test/thin-cli.test.js +382 -0
  233. package/dist/test/token-bootstrap.test.js +272 -0
  234. package/dist/test/token-devices.test.js +587 -0
  235. package/dist/test/token-lapse.test.js +94 -0
  236. package/dist/test/token-ring.test.js +188 -0
  237. package/dist/test/token-rotate-cli.test.js +58 -0
  238. package/dist/test/token-routes.test.js +95 -0
  239. package/dist/test/tool-uses.test.js +1006 -0
  240. package/dist/test/usage-ledger.test.js +126 -0
  241. package/dist/test/view-url.test.js +581 -0
  242. package/dist/test/wiki-links.test.js +57 -0
  243. package/dist/test/wiki-sources.test.js +85 -0
  244. package/dist/test/wiki-window.test.js +31 -0
  245. package/dist/test/wiki.test.js +399 -0
  246. package/dist/test/wordpiece.test.js +68 -0
  247. package/dist/tls.js +148 -0
  248. package/dist/tmux.js +202 -0
  249. package/dist/user-agent.js +46 -0
  250. package/docker-entrypoint.sh +141 -0
  251. package/docs/README.md +3 -0
  252. package/docs/absorb.md +231 -0
  253. package/docs/cost-ledger.md +125 -0
  254. package/docs/daemon-api.md +189 -0
  255. package/docs/diagrams.md +163 -0
  256. package/docs/doctor.md +36 -0
  257. package/docs/export-scope.md +69 -0
  258. package/docs/files-view.md +133 -0
  259. package/docs/link-previews.md +38 -0
  260. package/docs/math.md +32 -0
  261. package/docs/mcp.md +69 -0
  262. package/docs/memory-search.md +75 -0
  263. package/docs/mentions.md +101 -0
  264. package/docs/multi-brane.md +14 -0
  265. package/docs/passkeys.md +165 -0
  266. package/docs/presence.md +202 -0
  267. package/docs/releasing.md +53 -0
  268. package/docs/rendering-warnings.md +22 -0
  269. package/docs/request-layer.md +72 -0
  270. package/docs/selection-store.md +50 -0
  271. package/docs/session-affinity.md +61 -0
  272. package/docs/terminal-mirroring.md +211 -0
  273. package/docs/token-rotation.md +413 -0
  274. package/docs/view-urls.md +114 -0
  275. package/docs/web-app.md +23 -0
  276. package/docs/wiki.md +43 -0
  277. package/expo/dist/_expo/static/js/web/entry-e56efc1291dca7258ea00b8108b033a4.js +1097 -0
  278. package/expo/dist/apple-touch-icon.png +0 -0
  279. package/expo/dist/favicon.svg +3 -0
  280. package/expo/dist/index.html +177 -0
  281. package/expo/dist/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  282. package/expo/dist/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  283. package/expo/dist/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  284. package/expo/dist/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  285. package/expo/dist/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  286. package/expo/dist/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  287. package/expo/dist/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  288. package/expo/dist/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  289. package/expo/dist/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  290. package/expo/dist/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  291. package/expo/dist/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  292. package/expo/dist/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  293. package/expo/dist/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  294. package/expo/dist/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  295. package/expo/dist/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  296. package/expo/dist/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  297. package/expo/dist/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  298. package/expo/dist/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  299. package/expo/dist/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  300. package/expo/dist/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  301. package/expo/dist/katex/katex.min.css +1 -0
  302. package/expo/dist/manifest.json +16 -0
  303. package/expo/dist/metadata.json +1 -0
  304. package/expo/dist/og/membrane.v1.png +0 -0
  305. package/expo/dist/pdf.min.mjs +28 -0
  306. package/expo/dist/pdf.worker.min.mjs +28 -0
  307. package/expo/dist/sw.js +154 -0
  308. package/package.json +81 -23
  309. package/protocols/LIVE_loop.md +407 -0
  310. package/protocols/bebrief.md +41 -0
  311. package/protocols/digest.md +231 -0
  312. package/protocols/fly.md +266 -0
  313. package/protocols/idle.md +81 -0
  314. package/protocols/keeper.md +829 -0
  315. package/protocols/markdown.md +80 -0
  316. package/protocols/memory.md +419 -0
  317. package/protocols/mentions.md +93 -0
  318. package/protocols/payloads.md +53 -0
  319. package/protocols/prelude.md +91 -0
  320. package/protocols/ramify.md +105 -0
  321. package/protocols/review.md +356 -0
  322. package/protocols/rrr.md +232 -0
  323. package/protocols/scribe.md +429 -0
  324. package/protocols/summarize.md +203 -0
  325. package/protocols/twin.md +174 -0
  326. package/protocols/wiki.md +438 -0
  327. package/protocols/worker.md +38 -0
  328. package/wiki/shared/append-only-event-log.md +148 -0
  329. package/wiki/shared/index.md +48 -0
  330. package/wiki/shared/owning-your-narratives.md +161 -0
  331. package/wiki/shared/premature-ontologies.md +435 -0
  332. package/wiki/shared/sedimentary-superintelligence.md +128 -0
  333. package/wiki/shared/sequestering-the-narrative.md +143 -0
  334. package/wiki/shared/why-wikis-work.md +216 -0
  335. package/.npmignore +0 -2
  336. package/.travis.yml +0 -5
  337. package/index.js +0 -8
  338. package/index.js~ +0 -12
@@ -0,0 +1,80 @@
1
+ # Protocol: markdown
2
+
3
+ Everything you narrate is markdown, and it is read in more places than the chat. It lands in a phone's chat bubble tonight, a colleague's exported HTML file next week, and a search result next year. This page covers how to write for all three: what brane renders, what it adds to plain markdown, how readers find their way through long material, and what `narrate` tells you when something didn't render.
4
+
5
+ Read it before writing anything more elaborate than prose (a table, an equation, a diagram, a link into the code), and whenever a `narrate` result comes back with `warnings`.
6
+
7
+ ## Four places your words appear
8
+
9
+ Every surface supports the same markdown: GFM tables, task lists, autolinks and math. Math, code highlighting and diagrams run through the same code in the app and in the export, so an equation or a diagram looks the same in both. Links are where the surfaces differ:
10
+
11
+ | Surface | What is different there |
12
+ |---|---|
13
+ | **Chat** | The full treatment described below. Images arrive as payloads (see /payloads), not as `![](…)`. |
14
+ | **Files tab** | Renders `.md` files from the fold. Relative links and images resolve against the file's own directory. |
15
+ | **Wiki and protocol reader** | Links resolve against the page's slug, `#anchor` jumps to a section, and `/command` opens that protocol. |
16
+ | **HTML export** | A static snapshot with no script. `nid:seq` links become links to sibling files (`<nid>.html#seq-N`); `@mentions` and `/protocols` become plain text. |
17
+
18
+ ## What brane adds, and how to use it
19
+
20
+ **Cite anything by id.** Write `claude-4c7289d1:42` and the reader gets a link to that exact event; drop the `:42` to link the whole narrative. Only ids that exist become links, so a typo stays visible as text. A code span holding nothing but the id links too; inside a fenced block it stays inert.
21
+
22
+ > The fix landed in claude-4c7289d1:42, after the race was reproduced at claude-4c7289d1:37.
23
+
24
+ **Address someone with `@`.** `@claude-4c7289d1` notifies that narrative, while a bare id only cites it. Nothing else distinguishes the two, so use the `@` only when you mean it. Details are in /mentions.
25
+
26
+ **Name a protocol with a slash.** `/ramify` becomes a link to the protocol, but only if a protocol with that name exists and it isn't part of a path, so `src/memory` stays plain text.
27
+
28
+ **Link into the code with a relative path.** `[the handler](src/daemon/server.ts#L4880-L4900)` opens the Files tab on that file, scrolled to those lines and with them highlighted. `#L10`, `#L10-L20` and `?line=10-20` all work. Paths are relative to the narrative's fold, and a path starting with `/` goes nowhere. Line ranges apply to code files; a markdown file opens rendered, at the top.
29
+
30
+ **Write math however you like.** `$…$` and `\(…\)` render inline. `$$…$$` and `\[…\]` on their own lines, and ` ```math ` fences, render as display blocks. KaTeX draws all of them. A dollar sign that reads as money (`$10k–$500k`) is left as text. A ` ```latex ` fence stays a source listing, which is how to show TeX without rendering it.
31
+
32
+ **Name the language of a code fence.** Fences are highlighted server-side, and the language tag is how the highlighter knows what it's reading.
33
+
34
+ **Draw with mermaid.** A ` ```mermaid ` fence becomes a diagram. The supported dialect is the part agents actually use: `flowchart` and `graph`, the common node shapes, `subgraph`, and `classDef`/`style`. A node labelled with a real narrative id becomes a link. A diagram that can't be drawn falls back to highlighted source, and you get a warning.
35
+
36
+ **Style label text with a markdown string.** Write the label as ``A["`**Plan** mixin`"]``. The backticks just inside the quotes are mermaid's marker, not extra quoting. Inside one, `**bold**`, `*italic*` and `` `code` `` render, each new source line starts a new drawn line, and long lines wrap the way GitHub wraps them. In a plain label, `**` and backticks show as typed, here and on GitHub; only `<br/>`, `<b>`, `<i>`, `<code>`, `<u>` and `<s>` render there. To bold a whole node, use `classDef key font-weight:bold`. A node's markdown string may also hold a GFM table, which draws as a grid with a bold header and the alignment its `:---:` row asks for. Leave a blank line before any text that follows it, as in prose. Tables are brane's own: GitHub shows "Unsupported markdown" in their place, and in an edge label or subgraph title they show as source.
37
+
38
+ ````markdown
39
+ ```mermaid
40
+ flowchart LR
41
+ A[Report] --> B{Reproduced?}
42
+ B -->|yes| C[claude-4c7289d1]
43
+ ```
44
+ ````
45
+
46
+ **Wrap freely, here.** A single newline inside a paragraph renders as a space, so a hard-wrapped narration looks the same as an unwrapped one. That isn't true of a GitHub comment, where every newline becomes a line break. Anything headed for GitHub should be written unwrapped.
47
+
48
+ ## Pointing readers at the right part
49
+
50
+ A long conversation, wiki page or file is rarely read top to bottom. The best way to steer a reader to the one part that matters is to link to it rather than paste it, and each surface has a link form for that.
51
+
52
+ - **Chat** loads the last 50 events and loads more as the reader scrolls back. A `nid:seq` link opens a window centred on that event, so a citation reaches in one tap what scrolling would take minutes to find.
53
+ - **Wiki**: cite a section as `slug#anchor`. The reader, like `read_wiki` with a `window`, opens that section with its neighbours' headings around it.
54
+ - **Files** shows text files up to 2 MB, and offers larger ones as a download. To cite a passage of code, link a line range.
55
+ - **Export**: every row keeps its `#seq-N` anchor, even in an excerpt, so a `nid:seq` citation resolves in an exported file too.
56
+
57
+ ## Warnings
58
+
59
+ Every renderer here fails quietly, by design. If KaTeX can't parse an equation, the reader sees its source instead of red error text. A `$…$` that looks like money is shown as prose, and a code fence that is never closed swallows the rest of the message. That keeps the reader's view clean, but it leaves you, the writer, uninformed. So `narrate` tells you: whenever something in `say` won't render as written, the result carries a `warnings` array.
60
+
61
+ ```json
62
+ {
63
+ "kind": "math_parse_error",
64
+ "message": "Undefined control sequence: \\bogusmacro at position 1",
65
+ "fallback": "$\\bogusmacro{x}$",
66
+ "line": 12
67
+ }
68
+ ```
69
+
70
+ The kinds are `math_parse_error`, `math_demoted` (the currency guard took a `$…$` that was meant as math), `math_unclosed`, `fence_unclosed`, `diagram_unsupported`, `diagram_parse_error`, and `diagram_label_literal` (the diagram draws, but a label shows its markup as typed, and the message says how to style it instead).
71
+
72
+ **Read the `fallback` first.** It is the exact text the operator will see instead of what you meant, and it tells you whether your meaning got through:
73
+
74
+ - If the source of an equation still reads clearly, like `$E = mc^2$` or `$x_1 + x_2$`, it communicated. Nothing is owed.
75
+ - If the source doesn't read, like a `pmatrix` or a stack of `\frac`s, it communicated nothing.
76
+ - `fence_unclosed` is never harmless. Everything after the fence became one code block, so the rest of the message was lost.
77
+
78
+ **Fix it in the next narration, not the last one.** A warning arrives after the narration is already posted, so treat it as a receipt, not a veto. Re-sending something the operator already understood costs them as much attention as the original failure did, and an apology for a typographic blemish costs more than the blemish. Send a follow-up only when the meaning genuinely didn't arrive. In that case, narrate the substance again with `re` pointing at the original seq, so the two read as one thought.
79
+
80
+ **When it has to be exact, ask up front.** With `strict: true`, a narration that wouldn't render as written is never posted. The call fails with the same diagnostics, you fix the source, and you narrate again, with nothing left behind to correct. Save it for the narration that earns it, such as a derivation, a table the rest of the message depends on, or a document you're handing over. Don't make it a habit: each refusal is a round trip the operator has to wait through.
@@ -0,0 +1,419 @@
1
+ # Protocol: memory
2
+
3
+ Agent memory access through semantic search and cross-narrative context loading.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Agents have access to a memory system that indexes all past agent
10
+ conversations. This enables:
11
+
12
+ 1. **Activity Log** — see what's been worked on recently
13
+ 2. **Semantic Search** — find relevant past discussions by meaning
14
+ 3. **Cross-Narrative Loading** — pull context from other sessions
15
+ 4. **Knowledge Discovery** — build understanding across conversations
16
+
17
+ All memory features are available both as **MCP tools** (for use within
18
+ the LIVE loop) and as **CLI commands** (for operator use from the terminal).
19
+
20
+ ## Activity Log
21
+
22
+ Browse recently active narratives to understand what's been happening.
23
+
24
+ ### Using MCP (`narrative_info`)
25
+
26
+ ```json
27
+ {
28
+ "since": "1d",
29
+ "search": "auth",
30
+ "limit": 10
31
+ }
32
+ ```
33
+
34
+ Returns structured JSON with narrative metadata, event counts, and
35
+ relative timestamps. See the [LIVE_loop](LIVE_loop.md) protocol for
36
+ full parameter and response documentation.
37
+
38
+ ### Using the CLI
39
+
40
+ ```bash
41
+ brane memory log # Last 24 hours (default)
42
+ brane memory log --since 1w # Last week
43
+ brane memory log --search "auth" # Filter by content
44
+ brane memory log --status active # Only active narratives
45
+ brane memory log --fold . # Only this fold
46
+ brane memory log --limit 5 --json # JSON output
47
+ ```
48
+
49
+ Duration formats: `30m`, `1h`, `2d`, `1w`.
50
+
51
+ Example output:
52
+ ```
53
+ ● claude-4c7289d1 "Daemon refactor" 3m ago (42 events)
54
+ Summary: Done: added revive API endpoint
55
+ ○ claude-8b3ef201 "Expo keyboard" 2h ago (18 events)
56
+ Summary: Implementing multitouch modifier keys
57
+ ```
58
+
59
+ Each row shows:
60
+ - **Status indicator** — `●` active, `○` inactive
61
+ - **Narrative ID** — the agent session
62
+ - **Title** — narrative title or agent type fallback
63
+ - **Recency** — time since last event
64
+ - **Event count** — total events in the time window
65
+ - **Summary** — current narrative summary (if set)
66
+
67
+ ### When to Use
68
+
69
+ - **Situational awareness** — understand what other agents have been
70
+ working on before starting a new task
71
+ - **Find a narrative to resume** — locate a recent session by topic
72
+ - **Operator overview** — quick scan of recent activity across all agents
73
+
74
+ ## Semantic Search
75
+
76
+ ### Using MCP (`narrative_search`)
77
+
78
+ ```json
79
+ {
80
+ "query": "authentication flow",
81
+ "limit": 10
82
+ }
83
+ ```
84
+
85
+ Returns results ranked by semantic similarity. Auto-indexes unindexed
86
+ events on first call. See the [LIVE_loop](LIVE_loop.md) protocol for
87
+ full parameter and response documentation.
88
+
89
+ ### Using the CLI
90
+
91
+ ```bash
92
+ brane memory search "<query>" --limit 10
93
+ ```
94
+
95
+ Returns results ranked by semantic similarity with IDF filtering to
96
+ suppress common phrases.
97
+
98
+ Example output:
99
+ ```
100
+ 1. claude-4c7289d1 (seq 45) - Score: 0.62
101
+ "Checking for embedding model..."
102
+ > brane attach claude-4c7289d1
103
+ ```
104
+
105
+ Each result shows:
106
+ - **Narrative ID** — the agent session where this was found
107
+ - **Sequence number** — position in the conversation
108
+ - **Score** — semantic similarity (0-1, higher = more relevant)
109
+ - **Content preview** — truncated message content
110
+
111
+ ### Query Syntax
112
+
113
+ `narrative_search` (and `brane memory search`) accept a small query
114
+ grammar on top of plain keywords. Parsing is shared by the keyword
115
+ (FTS5) layer and the relevance-scoring layer, so the rules below apply
116
+ uniformly.
117
+
118
+ - **Bare terms.** Whitespace-separated words are ANDed together and
119
+ prefix-matched: `daemon restart` matches content containing a
120
+ `daemon…` token *and* a `restart…` token, in any order. Terms
121
+ shorter than 2 characters are dropped as noise.
122
+ - **Quoted phrases.** Wrap a span in quotes to require those tokens
123
+ **adjacent and in order**:
124
+ - `"context compaction"` — matches only where the two words appear
125
+ as a phrase.
126
+ - `"context compaction" recovery` — the phrase AND the prefix term
127
+ `recovery`.
128
+
129
+ Phrases compose freely with bare terms. Tokens inside a phrase
130
+ bypass the 2-character minimum (you quoted them deliberately).
131
+ - **Recognized quote pairs:**
132
+
133
+ | Pair | Codepoints | Typical source |
134
+ |-------|-----------------|--------------------------------|
135
+ | `"…"` | U+0022 / U+0022 | typed straight quotes |
136
+ | `“…”` | U+201C / U+201D | iOS/macOS smart-quote autosub |
137
+ | `‘…’` | U+2018 / U+2019 | smart single quotes |
138
+
139
+ ASCII `'` (U+0027) is **deliberately not** a phrase delimiter, so
140
+ contractions and possessives (`don't`, `it's`, `agent's`) keep
141
+ working as ordinary bare terms.
142
+ - **Lenient parsing.** An opening quote with no matching closer is
143
+ read to end-of-input rather than rejected — a trailing `"foo bar`
144
+ still searches for the phrase `foo bar`. There is no escape
145
+ mechanism: the first matching closer always ends a phrase.
146
+ - **Scoring.** A quoted-phrase hit in a result's content adds a
147
+ larger relevance boost (`+1.0`) than a bare-term hit (`+0.5`),
148
+ because phrase adjacency is much more discriminating evidence.
149
+ Consequence: phrase-bearing results can score above the nominal
150
+ `0…1` similarity range — treat scores as a *ranking signal*, not
151
+ an absolute probability.
152
+
153
+ ### Search Tips
154
+
155
+ 1. **Start with short phrases** — "authentication" outperforms "how does
156
+ the authentication flow work." Embedding models reward concept density.
157
+ 2. **Try multiple queries** — search is cheap. Run several single-concept
158
+ searches rather than one compound query.
159
+ 3. **Add qualifiers incrementally** — if a keyword is too broad, add one
160
+ word at a time.
161
+ 4. **Quote multi-word phrases for exact matches** — see *Query Syntax*
162
+ above for the full grammar (phrases, smart quotes, the apostrophe
163
+ carve-out, and scoring).
164
+
165
+ ## Cross-Brane Search
166
+
167
+ A single daemon can host multiple branes — typically the caller's home
168
+ brane plus one or more *foreign* branes created by `brane absorb`
169
+ when importing conversation history from other LLM providers
170
+ (ChatGPT exports, earlier brane instances, etc.). Foreign branes can
171
+ contain thousands of absorbed narratives that are highly relevant to
172
+ a search but invisible by default.
173
+
174
+ Both `narrative_search` and `narrative_info` default to **the
175
+ caller's own brane only**. To reach absorbed history, you must
176
+ explicitly pass `brane_ids`.
177
+
178
+ ### Discovery: `list_branes`
179
+
180
+ Call `list_branes` (no arguments) to see every brane the daemon
181
+ hosts. The response is keyed by brane ID, with a top-level `home`
182
+ field naming the caller's own brane:
183
+
184
+ ```json
185
+ {
186
+ "home": "brane-f66d2b",
187
+ "brane-f66d2b": { "narrative_count": 348, "active_count": 4, "absorbed_count": 1, "last_activity": 1777649907322 },
188
+ "brane-chatgpt-ad15b7": { "narrative_count": 1031, "active_count": 0, "absorbed_count": 1000, "last_activity": 1776028258570 },
189
+ "brane-import-3e91c4": { "narrative_count": 221, "active_count": 0, "absorbed_count": 219, "last_activity": 1774143494724 }
190
+ }
191
+ ```
192
+
193
+ The `absorbed_count` field is the strongest signal that a brane is
194
+ worth widening the search to: a brane with hundreds or thousands of
195
+ absorbed narratives almost certainly holds prior context the home
196
+ brane lacks. See the [LIVE_loop](LIVE_loop.md) protocol for full
197
+ `list_branes` documentation.
198
+
199
+ ### Pattern: expand on completeness gaps
200
+
201
+ When a home-brane search returns thin results — few hits, low
202
+ scores, or only narratives that *reference* the topic without
203
+ discussing it in depth — re-run the search with `brane_ids` covering
204
+ the foreign branes:
205
+
206
+ ```json
207
+ {
208
+ "query": "authentication flow",
209
+ "brane_ids": ["brane-f66d2b", "brane-chatgpt-ad15b7", "brane-import-3e91c4"]
210
+ }
211
+ ```
212
+
213
+ The same `brane_ids` parameter exists on `narrative_info`, useful
214
+ when you want to browse recent foreign-brane activity rather than
215
+ search for a specific phrase.
216
+
217
+ ### When to widen by default
218
+
219
+ Widen the search proactively (without waiting for thin results) when
220
+ the question is about long-running history or design rationale that
221
+ predates the current brane: project origins, prior architectural
222
+ decisions, abandoned approaches, or anything explicitly framed as
223
+ "have we ever…", "what did we decide about…", or "how did we used
224
+ to…". For narrow, current-state questions ("what's the schema right
225
+ now?"), the home brane is usually sufficient.
226
+
227
+ Avoid blindly always passing every brane — foreign branes can be
228
+ large and noisy, and a focused home-brane query is often higher
229
+ signal. Use `list_branes` to make the choice deliberately.
230
+
231
+ ## Wiki Consultation (Required)
232
+
233
+ Every memory search must also consult the wiki. Wiki files are a
234
+ curated, human-maintained knowledge base distinct from the narrative
235
+ event log: the narrative archive (`narrative_search`) and the wiki
236
+ (`search_wiki`) are **separate indices**, so searching the archive
237
+ alone silently misses anything that has been synthesized into wiki
238
+ form. The two reach different sources — `narrative_search` over
239
+ narrative events, the wiki tools over the `brane` package wiki (brane's
240
+ own vantage point, shipped with the install) plus any per-fold wikis.
241
+
242
+ The rule is simple: whenever you run `narrative_search` or
243
+ `narrative_info`, also consult the wiki for the same topic via the
244
+ dedicated wiki tools.
245
+
246
+ ### The wiki tools
247
+
248
+ | Tool | Reach for it to |
249
+ |------|-----------------|
250
+ | `list_wiki` | Browse the catalog — page slugs, human-authored descriptions, and the `source` of each (package `brane` vs a per-fold wiki). The cheapest way to see what's covered. |
251
+ | `read_wiki` | Fetch a page by `slug` (source auto-resolves when unique), or just one section via `anchor`. Returns the page's TOC and a `slug` / `slug#anchor` citation — the wiki analogue of `nid:seq`. |
252
+ | `search_wiki` | Semantic + keyword search over wiki content, returning chunk-level `slug#anchor` hits ranked by relevance — like `narrative_search`, but over the wikis. |
253
+
254
+ All three default to the package wiki plus the caller's fold; pass
255
+ `all: true` to widen to every registered fold's wiki. Every result
256
+ carries its `source`, so provenance is always explicit — you can never
257
+ mistake brane-canonical content for fold-local content.
258
+
259
+ ### Procedure
260
+
261
+ 1. **Search or browse.** Run `search_wiki` for the topic alongside your
262
+ `narrative_search`; or `list_wiki` to scan the catalog when you want
263
+ the lay of the land. Both are cheap.
264
+ 2. **Read what matches.** `read_wiki` the hit — whole page, or the
265
+ `anchor` section the search returned.
266
+ 3. **Treat the wiki as authoritative for its scope.** A wiki page
267
+ exists because the operator curated it — it is a synthesis that
268
+ has been reviewed, not a raw narration. If the wiki contradicts
269
+ what archive search surfaces, prefer the wiki while noting the
270
+ conflict in your answer; drift may be a legitimate finding for a
271
+ future `/wiki audit`.
272
+ 4. **Cite the wiki when you use it, with its source.** Use the
273
+ `slug` / `slug#anchor` citation `read_wiki`/`search_wiki` return, and
274
+ name the `source` when it isn't the package wiki, the same way
275
+ `nid:seq` citations work for narrative sources.
276
+
277
+ ### Why this is mandatory
278
+
279
+ The wiki captures syntheses that are expensive to re-derive from raw
280
+ narrations: a single wiki page can compress dozens of cross-brane
281
+ discussions into one audited paragraph. Skipping it means either
282
+ re-deriving the synthesis from scratch (wasting tokens and time) or
283
+ answering without it (missing the synthesis entirely and regressing
284
+ to whatever the archive search happens to surface). Neither is an
285
+ acceptable default.
286
+
287
+ This mandate applies to:
288
+
289
+ - Questions about any topic covered in the wiki — always.
290
+ - Open-ended questions where the wiki *might* cover the topic — check
291
+ before answering.
292
+ - `/memory` invocations that ask for a scan of recent activity — still
293
+ check `wiki/index.md` for context, even though the primary output is
294
+ activity-based.
295
+
296
+ See also the [`/wiki` protocol](wiki.md) for the rules governing how
297
+ the wiki itself is read and written.
298
+
299
+ ## Cross-Narrative Context Loading
300
+
301
+ Listen on another narrative to load its signal history into your context.
302
+
303
+ ### How It Works
304
+
305
+ ```json
306
+ {
307
+ "after": {
308
+ "claude-4c7289d1": 0
309
+ },
310
+ "wait": false
311
+ }
312
+ ```
313
+
314
+ Use `limit` to paginate through long histories, advancing the cursor to
315
+ the highest returned seq each time.
316
+
317
+ ### Use Cases
318
+
319
+ 1. **Resume knowledge** — load context from a previous session
320
+ 2. **Cross-reference** — see what was discussed in related narratives
321
+ 3. **Build connections** — explore related discussions
322
+
323
+ ### Example Workflow
324
+
325
+ Using MCP tools (within LIVE loop):
326
+ ```
327
+ 1. Search: narrative_search { "query": "authentication flow" }
328
+ -> Finds claude-4c7289d1 (seq 42)
329
+
330
+ 2. Load context: listen { "after": { "claude-4c7289d1": 0 }, "wait": false }
331
+ -> Receive full signal history
332
+
333
+ 3. Synthesize: context is now in your conversation
334
+ -> Reference, build upon, or continue that work
335
+ ```
336
+
337
+ Using CLI (from terminal):
338
+ ```
339
+ 1. Search: brane memory search "authentication flow"
340
+ -> Finds claude-4c7289d1 (seq 42)
341
+
342
+ 2. Attach: brane attach claude-4c7289d1
343
+ -> Load context interactively
344
+ ```
345
+
346
+ ## Technical Details
347
+
348
+ ### Storage
349
+
350
+ - **Engine**: SQLite with sqlite-vec extension
351
+ - **Vectors**: sentence-transformer embeddings (384 dimensions)
352
+ - **Index**: vec0 virtual table with cosine distance
353
+ - **Filtering**: IDF-based penalty for common content
354
+ - **Model cache**: `~/.brane/models/` (downloaded on first use)
355
+
356
+ ### Indexing
357
+
358
+ ```bash
359
+ brane memory index
360
+ ```
361
+
362
+ Indexing is idempotent and safe to run repeatedly. Only processes new or
363
+ changed events.
364
+
365
+ ### What Gets Indexed
366
+
367
+ - Agent narrations and signals from the SQLite events table
368
+ - Each message embedded with surrounding context for better retrieval
369
+
370
+ ## Best Practices
371
+
372
+ 1. **Consult the wiki first** — `search_wiki`/`list_wiki`/`read_wiki`
373
+ reach the wiki, which lives in a separate index from
374
+ `narrative_search`; run them before or alongside an archive search
375
+ or you'll miss anything synthesized into wiki form
376
+ 2. **Search before asking** — check if a topic was discussed before
377
+ 3. **Load full context** — don't rely only on search snippets
378
+ 4. **Cross-reference** — multiple narratives may cover the same topic
379
+ 5. **Widen across branes when context is incomplete** — `narrative_search`
380
+ and `narrative_info` default to the caller's home brane only. Use
381
+ `list_branes` to discover foreign (absorbed) branes and pass their
382
+ IDs via `brane_ids` whenever home-brane results look thin or the
383
+ question concerns history that predates the home brane (see
384
+ *Cross-Brane Search* above)
385
+
386
+ ### Combining Wiki, Log, Search, and Context Loading
387
+
388
+ ```
389
+ 1. Wiki: search_wiki { "query": "authentication flow" } (and/or list_wiki)
390
+ -> Establish what has already been synthesized on the topic
391
+
392
+ 2. Browse: narrative_info { "since": "1d" }
393
+ -> Spot claude-4c7289d1 working on auth
394
+
395
+ 3. Deep search: narrative_search { "query": "authentication flow" }
396
+ -> Find specific events across all time
397
+
398
+ 4. Load context: listen on claude-4c7289d1 with cursor 0
399
+ -> Pull full history into your session
400
+ ```
401
+
402
+ ## Limitations
403
+
404
+ - Semantic gap — embedding model may not capture all relationships
405
+ - No terminal history — only narrations/signals are indexed
406
+ - **Wiki is a separate index** — `./wiki/*.md` pages are not part of the
407
+ `narrative_search` index; reach them via `search_wiki`/`list_wiki`/
408
+ `read_wiki` (see *Wiki Consultation* above), never expecting them to
409
+ surface in `narrative_search`
410
+ - Indexing runs on demand via `brane memory index` or auto-triggers
411
+ on first `narrative_search` call; the wiki index self-syncs on each
412
+ `search_wiki` call (re-embedding only changed sections)
413
+
414
+ ## Related Protocols
415
+
416
+ - **[LIVE_loop](LIVE_loop.md)** — core communication loop
417
+ - **[wiki](wiki.md)** — the curated, human-maintained knowledge base
418
+ that every memory search must consult alongside the narrative
419
+ archive
@@ -0,0 +1,93 @@
1
+ # Protocol: mentions
2
+
3
+ How to address another narrative with `@nid`, and what to do when you are
4
+ addressed. Read it when a `listen`, `narrate` or `whoami` result carries
5
+ a `mentions` array, or when the operator tells you to check your mentions.
6
+
7
+ **Checking your mentions.** Call `whoami`: it reports recent mentions of
8
+ you, settled or not, and settles nothing. Then read each entry's `src`
9
+ narrative through your cursor (see
10
+ [Acknowledging them](#acknowledging-them)); reading is what settles it.
11
+
12
+ Writing `@claude-4c7289d1` anywhere you write prose **addresses** that
13
+ narrative. Writing the bare `claude-4c7289d1` merely **cites** it. The `@` is
14
+ the entire difference, and it has to be: narratives quote each other's ids
15
+ constantly, and if a citation notified, every design discussion would page half
16
+ the brane.
17
+
18
+ Reach for a mention when you want another agent's *attention* without putting a
19
+ message in its narrative. Foreign narration is the louder instrument — it
20
+ appends to that agent's own log, where it sits in its history forever. A
21
+ mention leaves the other narrative untouched and simply points at what you
22
+ wrote in yours. (`re` is quieter still: a back-reference notifies nobody.)
23
+
24
+ | You want to | Use |
25
+ |---|---|
26
+ | Put a message in another agent's conversation | `narrate` with its `nid` |
27
+ | Get its attention on something you wrote in yours | `@<nid>` |
28
+ | Link two events for a reader | `re` |
29
+
30
+ **A mention never revives.** If the agent isn't running, nothing starts it —
31
+ the mention waits, and the operator decides. So don't expect a reply from a
32
+ narrative that isn't live, and don't mention as a way to wake something up.
33
+
34
+ ## Receiving them
35
+
36
+ `listen`, `narrate` and `whoami` grow a `mentions` array **when you have some**
37
+ — a call with none is byte-identical to what it always returned. Each entry is
38
+ a *pointer*, not a copy:
39
+
40
+ ```json
41
+ { "id": 7, "src": "claude-4c7289d1", "seq": 42,
42
+ "author": "goose-aa11bb22", "time": 1787843821417 }
43
+ ```
44
+
45
+ `src` is the narrative to go read; `seq` is the event within it (`src:seq` is
46
+ the citable form); `author` is who wrote it, which differs from `src` when
47
+ someone narrated into a third narrative. `brane_id` appears only when the
48
+ mention came from another brane. `mentions_pending` counts any beyond the
49
+ receipt's cap.
50
+
51
+ Events you are handed also carry their own `mentions: [nid, …]` when they
52
+ address someone, so you can see it where you are already reading.
53
+
54
+ **This is heavier than `warnings`.** They share the "only when non-empty"
55
+ shape, but an ignored warning is a typographic blemish and an ignored mention
56
+ is a dropped message.
57
+
58
+ ## Acknowledging them
59
+
60
+ **Reading the narrative settles the mention.** There is no ack tool and nothing
61
+ to remember: pass the source narrative in your cursor, the way you already
62
+ would —
63
+
64
+ ```json
65
+ { "after": { "self": 42, "claude-4c7289d1": 17 } }
66
+ ```
67
+
68
+ — and the mentions carried by the events you receive are settled by that act.
69
+ Only the events actually returned count, so a `before`- or `tail`-bounded read
70
+ settles only what it showed you.
71
+
72
+ **A mention you don't read keeps coming back.** It wakes you once, then stays
73
+ in every receipt until you go and look. That is deliberate: delivery alone is
74
+ not attention, and a message can be received and still be missed.
75
+
76
+ Two escape hatches on `listen`, both rare:
77
+
78
+ - `mentions: "all"` — replay recent mentions whether or not they were settled.
79
+ The recovery read: delivery is at-most-once, so if you suspect one went
80
+ missing, this is where to look. `whoami` reports the same thing and settles
81
+ nothing, which makes it the right first call after a restart.
82
+ - `mentions: "dismiss"` — settle everything outstanding. For a mention you have
83
+ judged irrelevant and do not intend to read, which would otherwise reappear
84
+ forever. Use it deliberately; it is how a message gets dropped on purpose.
85
+
86
+ ## What is and isn't a mention
87
+
88
+ The handle is parsed from the *rendered* markdown, not the source text, so a
89
+ handle inside a fenced block, a code span, a URL or an existing link is inert —
90
+ pasting a log that mentions someone doesn't page them. A handle must start a
91
+ word (`ben@claude-4c7289d1` is neither an e-mail nor a mention), it is
92
+ case-sensitive, and it must name a narrative that exists. Mentioning the
93
+ narrative you are writing in does nothing: the message is already there.
@@ -0,0 +1,53 @@
1
+ # Protocol: payloads
2
+
3
+ How to receive, analyze, and send file payloads (typically images) over
4
+ the LIVE loop. This is split out of the core [LIVE_loop](LIVE_loop.md)
5
+ protocol so the core stays lean; read this only when an event carries a
6
+ payload or you need to attach one.
7
+
8
+ Events may carry file payloads — typically images pasted or uploaded by
9
+ the operator. The `payloads` field is an array of relative file paths
10
+ (e.g., `["claude-abc/1709251200000_0.png"]`).
11
+
12
+ ## Receiving payloads
13
+
14
+ When a `human_signal` or `agent_signal` event contains `payloads`,
15
+ the files are stored on disk at `~/.brane/payloads/{path}`. To read
16
+ a payload, construct the absolute path:
17
+
18
+ ```
19
+ ~/.brane/payloads/ + payloads[0]
20
+ ```
21
+
22
+ Then read that absolute path with your harness's file-read tool —
23
+ most handle images natively (PNG, JPG, etc.).
24
+
25
+ ## Image analysis delegation
26
+
27
+ Reading large images directly into your main context is expensive.
28
+ When possible, delegate to a sub-agent:
29
+
30
+ 1. Spawn a sub-agent (Haiku or Sonnet) with the payload path and a
31
+ specific question
32
+ 2. The sub-agent reads the image via `Read` and narrates findings
33
+ back as a foreign narration
34
+ 3. You receive the analysis as an `agent_signal` event
35
+
36
+ If delegation produces insufficiently specific results, narrate to
37
+ the operator that you need to read the image directly, then proceed.
38
+
39
+ ## Sending payloads
40
+
41
+ To attach files to your narrations, pass absolute file paths in the
42
+ `payloads` parameter of the `narrate` tool:
43
+
44
+ ```json
45
+ {
46
+ "say": "Here's a screenshot of the error",
47
+ "after": 42,
48
+ "payloads": ["/tmp/screenshot.png"]
49
+ }
50
+ ```
51
+
52
+ The daemon copies files into managed storage. The operator sees them
53
+ rendered inline in the web UI.