brane 0.1.1 → 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 (348) 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 +79 -27
  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/.travis.yml +0 -7
  336. package/lib/brane.cjs.js +0 -12
  337. package/lib/brane.cjs.js.map +0 -1
  338. package/lib/brane.d.ts +0 -11
  339. package/lib/brane.js +0 -6
  340. package/lib/brane.js.map +0 -1
  341. package/lib/tests.d.ts +0 -1
  342. package/lib/tests.js +0 -8
  343. package/lib/tests.js.map +0 -1
  344. package/rollup.config.js +0 -21
  345. package/scripts/test.sh +0 -8
  346. package/src/brane.ts +0 -21
  347. package/src/tests.ts +0 -8
  348. package/tsconfig.json +0 -16
@@ -0,0 +1,203 @@
1
+ # /summarize [guidance]
2
+
3
+ Consolidate a session into a durable summary narration — the nap that
4
+ lets a fresh session pick up without re-learning what just happened.
5
+
6
+ ## Why summarize
7
+
8
+ A session accumulates context that is about to be lost: the context
9
+ window gets compacted or cleared, the agent session dies and is
10
+ revived, a twin takes over, or the operator simply returns tomorrow.
11
+ The narrative event log survives all of these — but a reader arriving
12
+ cold gets the log in event order, newest last, with the load-bearing
13
+ conclusions scattered among the play-by-play. A summary narration is
14
+ the consolidation pass that fixes this: one event, near the end of the
15
+ log, that a `listen(wait: false, tail: 50)` on re-entry finds
16
+ immediately, stating where things stand.
17
+
18
+ The framing comes from Erik Bylund's "Agents Need Sleep"
19
+ (erikbylund.com, 2026): memory needs **consolidation as a first-class
20
+ practice** — a light "nap" after each unit of work so that "a fresh
21
+ session tomorrow picks up without re-learning what just happened."
22
+ Consolidation's job is salience, compression, trust, and *forgetting*
23
+ — not retrieval, which search already handles. `/summarize` is the
24
+ nap, adapted to brane's substrate.
25
+
26
+ That substrate changes the risk profile. Bylund's central warning —
27
+ *"distillation concentrates error exactly as efficiently as it
28
+ concentrates signal"* — is about mutable state files, where the
29
+ summary silently replaces the record and a stale claim inherits full
30
+ authority. A brane summary is a narration: append-only, attributed,
31
+ timestamped, and sitting *beside* the events it summarizes rather than
32
+ over them. It cannot erase anything, and every claim in it can carry
33
+ an `nid:seq` citation back to the event it came from. That is the
34
+ discipline this protocol enforces: a summary is a **checkable index
35
+ into the record**, not a replacement for it. Written this way, the
36
+ summary doubles as a **trailing table of contents** for the
37
+ narrative: its `nid:seq` backlinks — which the operator's UI
38
+ auto-linkifies into links that jump to the exact event — let a
39
+ reader navigate the whole session from one narration.
40
+
41
+ ## Audiences
42
+
43
+ Write for all of these at once, in roughly this priority:
44
+
45
+ 1. **Your future self** after a `/clear`, compaction, or revive —
46
+ reloading via `listen` and needing plan, stance, and in-flight
47
+ state back without re-reading everything.
48
+ 2. **A successor or twin** continuing the work with none of your
49
+ context (see the [twin](twin.md) protocol).
50
+ 3. **The operator**, catching up asynchronously — possibly on a
51
+ phone, possibly days later.
52
+ 4. **Future search and `/digest` runs** — the summary is the event
53
+ most worth surfacing for the whole session, so make it findable
54
+ and self-contained.
55
+
56
+ The quality bar is Bylund's stranger test: **could a stranger read
57
+ this one narration and know where things stand?** If understanding it
58
+ requires having watched the session, it is not done.
59
+
60
+ ## What a good session summary is
61
+
62
+ **A state snapshot, not a chronicle.** Report where things stand
63
+ *now* — not the order in which you got there. The sequence of
64
+ attempts, tool calls, and course corrections is already in the log in
65
+ perfect fidelity; re-telling it is the one thing a summary can never
66
+ do better than the record itself. Chronology earns a place only where
67
+ it explains the present ("X was tried before Y ruled it out").
68
+
69
+ **Forgetting is the job.** The append-only log is what makes
70
+ aggressive compression safe: nothing you omit is lost, only demoted to
71
+ search. Drop the routine and the resolved. What must *not* be dropped:
72
+ open threads, unanswered operator questions, and negative findings —
73
+ "we tried X and it failed because Y" is expensive knowledge that a
74
+ successor will otherwise re-purchase.
75
+
76
+ **Grounded, not remembered.** A wrong confident summary is worse than
77
+ no summary at all — it gets read *instead of* the record, so its
78
+ errors propagate with the full authority of consolidation. The rules
79
+ are the same as [/digest](digest.md)'s, and they are mandatory:
80
+
81
+ - Re-read the events before summarizing them. Your in-context memory
82
+ of the session may already be compacted prose; the log is not.
83
+ Report only what the log actually says.
84
+ - Cite claims as `nid:seq` so they are checkable — and so the summary
85
+ works as an entry point into `listen` / `narrative_search` for any
86
+ reader who needs the detail (see the [memory](memory.md) protocol).
87
+ Always the full `nid:seq` form: prose like "seq 42" is not
88
+ linkified, so it makes a claim checkable but not tappable.
89
+ - Repo facts (branch names, PR numbers, commit hashes, test results)
90
+ are copied from real `git`/`gh` output obtained this run, never
91
+ composed from memory to look precise.
92
+ - Attribute positions; don't assert them. Decisions are "the operator
93
+ directed…" / "we agreed…" with a citation, not settled fact. Don't
94
+ editorialize, sharpen vague outcomes into definite ones, or supply
95
+ motives the events don't give.
96
+ - Name your gaps instead of filling them. If part of the session is
97
+ unread or an outcome is unverified, say so plainly.
98
+
99
+ ## Interpreting guidance
100
+
101
+ `/summarize [guidance]` is freeform; interpret intent generously, as
102
+ `/digest` does. The default — bare `/summarize` or
103
+ `/summarize session` — is the current narrative, whole session,
104
+ general audience. Guidance can adjust any of:
105
+
106
+ - **Scope** — `/summarize since the last summary`,
107
+ `/summarize the last hour`, `/summarize the auth work only`
108
+ - **Audience** — `/summarize for a twin` (lean toward in-flight
109
+ state, gotchas, and next actions), `/summarize for the operator`
110
+ (lean toward outcomes and open questions)
111
+ - **Target** — `/summarize claude-4c7289d1`: summarize another
112
+ narrative, loading it first via `listen` with a cursor (see
113
+ *Cross-Narrative Context Loading* in [memory](memory.md)). Narrate
114
+ the summary into your own narrative unless directed otherwise.
115
+ - **Focus** — any topical emphasis the guidance names
116
+
117
+ ## Gathering
118
+
119
+ Ground the summary in the log, not in what you think you remember:
120
+
121
+ 1. Find your previous summary, if any — scan your own narrative for
122
+ the `**Session summary**` header (a `listen` re-read, or
123
+ `narrative_search` scoped by content). Its seq is your default
124
+ window start, and your `re` target for supersession.
125
+ 2. Re-read the window: `listen` with `wait: false` and `after` set to
126
+ the previous summary's seq (or `0` for the whole narrative —
127
+ paginate if long). Note the seqs of load-bearing events as you go:
128
+ operator direction, decisions, reversals, results.
129
+ 3. Corroborate externals — run `git`/`gh` for any repo state the
130
+ summary will assert; check that "done" things are actually merged,
131
+ pushed, or passing.
132
+
133
+ For long sessions, narrate brief progress as you gather, per the LIVE
134
+ loop's narrate-often principle.
135
+
136
+ ## Summary structure
137
+
138
+ Begin the narration with a header line:
139
+
140
+ ```
141
+ **Session summary** — {one-line gist} ({date})
142
+ ```
143
+
144
+ Then sections as needed, omitting any that are empty. Suggested
145
+ shape, not a rigid template — let the session's actual shape win:
146
+
147
+ - **Where things stand** — current state of the work: what exists,
148
+ what is verified working, what is merely drafted. Concrete
149
+ locations: branch, worktree, files, PRs.
150
+ - **Decisions** — direction set during the session, attributed and
151
+ cited (`nid:seq`). Include decisions *against* things.
152
+ - **Open threads** — in-flight work, unanswered questions, promised
153
+ follow-ups, blockers. This is the section a successor acts on
154
+ first; make each item actionable.
155
+ - **Lessons and dead ends** — negative findings worth keeping:
156
+ approaches ruled out and why, gotchas discovered, anything a
157
+ successor would otherwise re-learn the hard way.
158
+ - **Pointers** — key events (`nid:seq`), PRs/commits, files, wiki
159
+ pages (`slug#anchor`) for readers who need to go deeper. Together
160
+ with the citations woven through the sections above, this is the
161
+ trailing-table-of-contents role made explicit: every major beat of
162
+ the session reachable through a backlink.
163
+
164
+ Keep it compact — a summary that must be summarized has failed.
165
+ Compression is safe precisely because the pointers carry the depth.
166
+
167
+ ## Output
168
+
169
+ Narrate the summary in full via `narrate`, on one call that also:
170
+
171
+ - **Sets `meta.summary`** to a current one-liner for the narrative
172
+ list — e.g. `"Summarized: daemon refactor merged; expo tab bug
173
+ open"`. The narrated body and the metadata line serve different
174
+ readers (log vs. list); update both.
175
+ - **Back-references via `re`**: the previous `**Session summary**`
176
+ event if one exists (supersession by reference — the new summary
177
+ visibly succeeds the old, and the chain of summaries becomes
178
+ walkable), plus the load-bearing events the summary rests on.
179
+
180
+ Before posting, make one verification pass over the draft: every
181
+ claim, citation, and identifier — can you point to the event or
182
+ command output you read it from? Cut or flag anything you cannot.
183
+
184
+ ## Cadence
185
+
186
+ `/summarize` runs when the operator invokes it, but the natural
187
+ moments to *suggest* one (or, with standing permission, run one) are
188
+ exactly Bylund's nap boundaries: a unit of work just completed, a
189
+ `/clear` or handoff is imminent, or the session is winding down. A
190
+ summary written while context is still warm is cheap; the same
191
+ summary reconstructed after context loss is expensive and worse.
192
+
193
+ The heavier tier — Bylund's "deep sleep," where accumulated summaries
194
+ are themselves challenged against reality and distilled — is not this
195
+ protocol. Cross-narrative consolidation belongs to [/digest](digest.md)
196
+ (activity over a time window) and the [/wiki](wiki.md) audit (curated
197
+ synthesis against the record).
198
+
199
+ ## After generating
200
+
201
+ Return to the LIVE loop — `listen` for further signals. The operator
202
+ may ask follow-ups, request a different focus, or use the summary as
203
+ the handoff point for a `/clear` or twin spawn.
@@ -0,0 +1,174 @@
1
+ # Protocol: twin
2
+
3
+ A **twin** is a brane-managed agent spawned to continue from a
4
+ **predecessor** narrative — inheriting its history and, when the
5
+ predecessor is still live, tracking it in real time. Twinning is how an
6
+ external or absorbed session's context is brought into brane as a
7
+ first-class, revivable narrative without disturbing the original.
8
+
9
+ This protocol is **role-bound**: it is binding on agents who hold
10
+ `role: "twin"`. For everyone else it is informational. Roles are
11
+ superpositional (see the prelude's "Role-bound protocols"): a twin
12
+ can be steered by the operator to *also* hold another role — most
13
+ naturally `keeper`, scoped to its predecessor — and then both
14
+ protocols bind it jointly. See "A twin as a single-purpose keeper"
15
+ below.
16
+
17
+ **Prerequisite:** this protocol uses the LIVE loop's tools and
18
+ vocabulary (`listen`, `narrate`, `whoami`, `narrative_info`, etc.). If
19
+ you have not already read `protocols/LIVE_loop.md`, read it first; then
20
+ return here.
21
+
22
+ ## What a twin is for
23
+
24
+ The operator spawned you to adopt a predecessor narrative — typically an
25
+ **external** MCP session (an agent that connected without `brane spawn`)
26
+ or an **absorbed** import. The predecessor may be:
27
+
28
+ - **Over** — disconnected or finished. You are importing a closed
29
+ history, the way an absorbed narrative is activated.
30
+ - **Still live** — an external client may still be connected and
31
+ appending events *after* the point you were forked from. You are then
32
+ a real-time twin: you continue the work *alongside* it, not just from
33
+ a snapshot.
34
+
35
+ You will not know which until you look — so this protocol has you treat
36
+ the predecessor as **possibly live** by default.
37
+
38
+ ## Step 1 — Find your predecessor
39
+
40
+ Your predecessor is recorded in your **own `started` event's `re`**, in
41
+ `nid:seq` form (e.g. `external-9f3a1c20:42`). Read it:
42
+
43
+ ```json
44
+ { "tail": 1, "after": 0 }
45
+ ```
46
+
47
+ The `re` entry's `nid` is your predecessor; its `:seq` is the **boundary
48
+ seq** — the last event that existed in the predecessor when you were
49
+ forked. Everything in the predecessor **through that seq is your
50
+ inherited prefix**; anything past it (if any) is new activity that
51
+ arrived after the fork.
52
+
53
+ If your `started` event carries no `re`, you have no predecessor — fall
54
+ back to the plain LIVE loop.
55
+
56
+ ## Step 2 — Read the inherited prefix
57
+
58
+ Read the predecessor's history up to the boundary seq and process it as
59
+ your own context:
60
+
61
+ ```json
62
+ { "after": { "<predecessor-nid>": 0 } }
63
+ ```
64
+
65
+ Keep advancing the cursor (`{ "<predecessor-nid>": <last-seq-seen> }`)
66
+ until you have read through the boundary seq. If there are many events,
67
+ page until you reach it. This is the salient context you were spawned to
68
+ carry forward — understand it before acting.
69
+
70
+ The prefix may be **thin or empty** — e.g. a freshly-connected external
71
+ client whose only event is its connection. That's fine: carry forward
72
+ whatever is there and move on. This step earns its keep when twinning an
73
+ absorbed import or a long-running session; for a brand-new predecessor
74
+ there is simply little to inherit.
75
+
76
+ ## Step 3 — Twin the live loop
77
+
78
+ From now on, **LIVE-loop with a multi-narrative cursor over both your
79
+ own narrative and the predecessor's**, so you stay in sync if the
80
+ predecessor is still active:
81
+
82
+ ```json
83
+ { "after": { "self": <your-last-seq>, "<predecessor-nid>": <boundary-seq> } }
84
+ ```
85
+
86
+ - Advance **both** keys as events arrive.
87
+ - New events from the predecessor past the boundary seq are the live
88
+ session continuing — interpret them as fresh signals, not history.
89
+ - If the predecessor is over, this watch simply yields nothing extra and
90
+ you behave like any other agent. No special-casing needed.
91
+
92
+ ## Step 4 — Wait for operator direction
93
+
94
+ DO NOT under any circumstances begin executing actions (_especially_
95
+ contacting the previous agent) before you have explicit direction from
96
+ the operator, as this skips the L, I, and V steps of the LIVE loop. Do
97
+ not even speculate about the nature of the task before you actually
98
+ know, even if the operator has not yet said anything, as this will
99
+ confuse future readers if you happen to be wrong. Wait.
100
+
101
+ ## Step 5 — Coordinate, don't collide
102
+
103
+ **First, find out whether a peer is actually live** — don't assume. A
104
+ predecessor narrative may have a live agent on the other end, or it may
105
+ be **dormant**: an external client that has since disconnected, or a
106
+ narrative the operator is simply using as a second channel to type into.
107
+ Check before you worry about collision:
108
+
109
+ - Call `narrative_info` with the predecessor's nid and look at
110
+ `mcp_connected` (and `status`), and/or `list_peers` to see whether it
111
+ appears as an active peer.
112
+ - **No agent connected →** there is no one to collide with. Every event
113
+ there is the operator (or your own foreign-narration); you are simply
114
+ the sole live agent rooted in two narratives. Keep watching it (it's
115
+ nearly free and the operator may use it as a channel), but drop the
116
+ coordination ceremony.
117
+ - **An agent *is* connected →** treat it as a true peer. Coordinate
118
+ explicitly and don't duplicate its actions.
119
+
120
+ When a peer is live, avoid both agents thinking they alone are driving:
121
+
122
+ - **Your own narrative is your voice.** Narrate your work into `self`.
123
+ - **Once you have permission to communicate with your predecessor, use
124
+ foreign-narration** (`narrate` with `nid: "<predecessor-nid>"`) to
125
+ coordinate. Your message arrives there as an `agent_signal`.
126
+ - **Defer to operator direction over assumptions about who owns what.**
127
+ You have not "inherited" any work until the operator says so, and you
128
+ are not entitled to suggest any division of labor between the agents.
129
+
130
+ ## Extend, don't replace
131
+
132
+ A twin continues *from* its predecessor — it does not take it over. The
133
+ predecessor narrative stays intact as the historical record; you branch
134
+ from it and carry its context forward, leaving the original where it is.
135
+
136
+ ## A twin as a single-purpose keeper
137
+
138
+ A twin is already most of a [keeper](keeper.md) scoped to one
139
+ narrative, so the operator may steer a newborn twin to *also* keep
140
+ watch over its predecessor. When that happens you hold both roles at
141
+ once (see the prelude's "Role-bound protocols") and read `keeper.md`
142
+ as binding, not merely informational — no cognitive dissonance over a
143
+ `whoami` that still says `twin`.
144
+
145
+ The fit is natural because the twin machinery *is* the keeper machinery
146
+ in miniature:
147
+
148
+ - **Context for free.** A daemon-wide keeper starts cold and
149
+ reconstructs an agent's state from its tmux pane. You inherited the
150
+ predecessor's prefix (Step 2), so you oversee from *inside* its
151
+ context.
152
+ - **The watch set is already built.** A keeper maintains a cursor map
153
+ over every active narrative; yours is just the two keys you already
154
+ multi-listen on — `{ self, <predecessor> }` (Step 3). No
155
+ `list_peers` reconciliation loop to run.
156
+ - **Scope, not singleton.** There's no one-keeper-per-daemon rule
157
+ (keeper.md, "Scoped, not singleton"); keepers with disjoint
158
+ scopes coexist. A twin-keeper is scoped to one predecessor, so it
159
+ rarely collides — other single-purpose keepers watch different
160
+ narratives, and a global keeper can simply cede your predecessor to
161
+ you. The only thing to watch for is another keeper *also*
162
+ authoritative over your predecessor; if you spot that, notify the
163
+ operator and coordinate (per keeper.md Step 3) rather than either
164
+ of you racing on its prompts. You don't run the daemon-wide keeper's
165
+ startup overlap sweep — your scope is one narrative — you just stay
166
+ alert to that one overlap case.
167
+
168
+ Apply `keeper.md`'s constraints in full over that one narrative: the
169
+ irreversibility ceiling, defer-to-operator gating, narration-before-
170
+ action audit format, and the hands-off rule for idled agents all bind
171
+ you. Where the twin and keeper protocols differ, the more conservative
172
+ instruction wins. Your own narrative remains your audit log and your
173
+ voice; reach the predecessor by foreign-narration exactly as Step 5
174
+ describes.