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.
- package/AGENTS.md +362 -0
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +91 -0
- package/DESIGN.md +402 -0
- package/Dockerfile +61 -0
- package/LICENSE +656 -17
- package/README.md +174 -2
- package/SECURITY.md +205 -0
- package/dist/absorb/brane-id.js +11 -0
- package/dist/absorb/chatgpt.js +161 -0
- package/dist/absorb/claude-code.js +504 -0
- package/dist/absorb/index.js +543 -0
- package/dist/absorb/organelle.js +345 -0
- package/dist/absorb/run.js +520 -0
- package/dist/absorb/sources.js +168 -0
- package/dist/absorb/types.js +3 -0
- package/dist/agent-env.js +45 -0
- package/dist/agents.js +1168 -0
- package/dist/claude-live-session.js +124 -0
- package/dist/cli.js +50 -0
- package/dist/codex-tool-log.js +144 -0
- package/dist/commands/absorb.js +291 -0
- package/dist/commands/attach.js +31 -0
- package/dist/commands/certify.js +62 -0
- package/dist/commands/config.js +116 -0
- package/dist/commands/cost.js +126 -0
- package/dist/commands/daemon.js +350 -0
- package/dist/commands/doctor.js +262 -0
- package/dist/commands/fold.js +95 -0
- package/dist/commands/list.js +89 -0
- package/dist/commands/mcp.js +84 -0
- package/dist/commands/meld.js +332 -0
- package/dist/commands/memory.js +215 -0
- package/dist/commands/revive.js +74 -0
- package/dist/commands/run.js +85 -0
- package/dist/commands/spawn.js +1094 -0
- package/dist/commands/token.js +153 -0
- package/dist/copilot-tool-log.js +145 -0
- package/dist/cost/pricing.js +116 -0
- package/dist/cost/reprice.js +136 -0
- package/dist/crush-tool-log.js +293 -0
- package/dist/daemon/agent-scope.js +116 -0
- package/dist/daemon/awaiting.js +54 -0
- package/dist/daemon/cert-manager.js +349 -0
- package/dist/daemon/client.js +262 -0
- package/dist/daemon/gated-routes.js +112 -0
- package/dist/daemon/keep-awake.js +103 -0
- package/dist/daemon/local-socket.js +145 -0
- package/dist/daemon/presence-gate.js +206 -0
- package/dist/daemon/server.js +6349 -0
- package/dist/daemon/signal-source.js +35 -0
- package/dist/daemon/tailscale-rebind.js +58 -0
- package/dist/daemon/token-ring.js +263 -0
- package/dist/daemon/token-routes.js +190 -0
- package/dist/db/events.js +152 -0
- package/dist/db/mentions.js +179 -0
- package/dist/db/schema.js +633 -0
- package/dist/db/tokens.js +583 -0
- package/dist/db/tool-uses.js +647 -0
- package/dist/diagram/index.js +85 -0
- package/dist/diagram/label.js +455 -0
- package/dist/diagram/layout.js +476 -0
- package/dist/diagram/links.js +50 -0
- package/dist/diagram/metrics.js +152 -0
- package/dist/diagram/parse.js +487 -0
- package/dist/diagram/svg.js +389 -0
- package/dist/diagram/types.js +9 -0
- package/dist/export.js +629 -0
- package/dist/files/archive-types.js +2 -0
- package/dist/files/archive.js +182 -0
- package/dist/files/browse.js +327 -0
- package/dist/files/bytes.js +162 -0
- package/dist/files/codecs.js +33 -0
- package/dist/files/find.js +212 -0
- package/dist/files/tar.js +223 -0
- package/dist/files/zip.js +209 -0
- package/dist/folds.js +72 -0
- package/dist/grammars/ebnf.js +92 -0
- package/dist/highlight.js +250 -0
- package/dist/ids.js +24 -0
- package/dist/markdown-diagnostics.js +233 -0
- package/dist/math.js +168 -0
- package/dist/mcp/server.js +886 -0
- package/dist/memory/embedder.js +145 -0
- package/dist/memory/embedding-worker.js +71 -0
- package/dist/memory/embeddings.js +91 -0
- package/dist/memory/index.js +232 -0
- package/dist/memory/storage.js +587 -0
- package/dist/memory/wiki.js +688 -0
- package/dist/memory/wordpiece.js +247 -0
- package/dist/mentions-scan.js +40 -0
- package/dist/presence.js +259 -0
- package/dist/session-affinity.js +185 -0
- package/dist/shared/api-request.js +124 -0
- package/dist/shared/block-glyphs.js +114 -0
- package/dist/shared/diagram-css.js +17 -0
- package/dist/shared/export-selection.js +101 -0
- package/dist/shared/find-in-text.js +110 -0
- package/dist/shared/glow-hues.js +225 -0
- package/dist/shared/hex-dump.js +62 -0
- package/dist/shared/hex-pages.js +52 -0
- package/dist/shared/hit-drum.js +79 -0
- package/dist/shared/known-nids.js +58 -0
- package/dist/shared/list-scroll-keys.js +56 -0
- package/dist/shared/markdown-lists.js +72 -0
- package/dist/shared/markdown-math.js +485 -0
- package/dist/shared/markdown-mentions.js +79 -0
- package/dist/shared/markdown-nids.js +41 -0
- package/dist/shared/markdown-protocols.js +53 -0
- package/dist/shared/markdown-refs.js +123 -0
- package/dist/shared/membrane-invasion.js +342 -0
- package/dist/shared/membrane-motion.js +83 -0
- package/dist/shared/membrane-palette.js +253 -0
- package/dist/shared/membrane-terrain.js +212 -0
- package/dist/shared/message-selection.js +123 -0
- package/dist/shared/mo-glyph.js +57 -0
- package/dist/shared/narrative-format.js +237 -0
- package/dist/shared/narrative-menu.js +82 -0
- package/dist/shared/narrative-sort.js +47 -0
- package/dist/shared/narrative-status.js +52 -0
- package/dist/shared/no-pan.js +85 -0
- package/dist/shared/pane-layout.js +50 -0
- package/dist/shared/payload-inline.js +83 -0
- package/dist/shared/speaker-color.js +61 -0
- package/dist/shared/token-rotation.js +14 -0
- package/dist/shared/view-url.js +197 -0
- package/dist/shared/wiki-links.js +70 -0
- package/dist/shared/wiki-window.js +4 -0
- package/dist/tailscale.js +55 -0
- package/dist/test/absorb-claude.test.js +892 -0
- package/dist/test/agent-scope.test.js +193 -0
- package/dist/test/agents.test.js +55 -0
- package/dist/test/api-request.test.js +122 -0
- package/dist/test/awaiting-glow.test.js +54 -0
- package/dist/test/awaiting.test.js +122 -0
- package/dist/test/bind-token.test.js +88 -0
- package/dist/test/block-glyphs.test.js +68 -0
- package/dist/test/cert-manager.test.js +262 -0
- package/dist/test/claude-live-session.test.js +110 -0
- package/dist/test/codex-tool-log.test.js +568 -0
- package/dist/test/config.test.js +71 -0
- package/dist/test/copilot-tool-log.test.js +93 -0
- package/dist/test/cors-preflight.test.js +49 -0
- package/dist/test/cost-linger.test.js +31 -0
- package/dist/test/cost-pricing.test.js +72 -0
- package/dist/test/cost-reprice.test.js +139 -0
- package/dist/test/cost-sessions.test.js +301 -0
- package/dist/test/crush-tool-log.test.js +289 -0
- package/dist/test/daemon-client.test.js +109 -0
- package/dist/test/daemon-socket.test.js +293 -0
- package/dist/test/diagram-arrows.test.js +205 -0
- package/dist/test/diagram-export.test.js +210 -0
- package/dist/test/diagram-labels.test.js +313 -0
- package/dist/test/diagram-parse.test.js +191 -0
- package/dist/test/diagram-render.test.js +175 -0
- package/dist/test/diagram-review.test.js +288 -0
- package/dist/test/diagram-self-loop-labels.test.js +303 -0
- package/dist/test/embedder.test.js +84 -0
- package/dist/test/events.test.js +123 -0
- package/dist/test/export-selection.test.js +102 -0
- package/dist/test/export.test.js +505 -0
- package/dist/test/files-browse.test.js +393 -0
- package/dist/test/files-find.test.js +272 -0
- package/dist/test/find-in-text.test.js +86 -0
- package/dist/test/first-paint-viewport.test.js +59 -0
- package/dist/test/fixtures/embedding-golden.js +23 -0
- package/dist/test/fixtures/wordpiece-golden.js +167 -0
- package/dist/test/glow-hues.test.js +202 -0
- package/dist/test/harness-cost.test.js +423 -0
- package/dist/test/helpers.js +21 -0
- package/dist/test/hex-pages.test.js +68 -0
- package/dist/test/highlight.test.js +69 -0
- package/dist/test/hit-drum.test.js +71 -0
- package/dist/test/hook-config.test.js +262 -0
- package/dist/test/json-gzip.test.js +70 -0
- package/dist/test/key-routing.test.js +58 -0
- package/dist/test/known-nids.test.js +106 -0
- package/dist/test/link-preview.test.js +67 -0
- package/dist/test/list-scroll-keys.test.js +66 -0
- package/dist/test/listen-own-words.test.js +147 -0
- package/dist/test/listen-timeout.test.js +33 -0
- package/dist/test/markdown-diagnostics.test.js +121 -0
- package/dist/test/markdown-lists.test.js +182 -0
- package/dist/test/markdown-math.test.js +256 -0
- package/dist/test/markdown-nids.test.js +146 -0
- package/dist/test/markdown-protocols.test.js +139 -0
- package/dist/test/mcp-bridge-cancel.test.js +98 -0
- package/dist/test/mcp-bridge-reconnect.test.js +121 -0
- package/dist/test/mcp-narrative.test.js +193 -0
- package/dist/test/mcp.test.js +548 -0
- package/dist/test/meld.test.js +85 -0
- package/dist/test/membrane-invasion.test.js +482 -0
- package/dist/test/membrane-motion.test.js +101 -0
- package/dist/test/membrane-palette.test.js +166 -0
- package/dist/test/membrane-terrain.test.js +170 -0
- package/dist/test/memory-log.test.js +202 -0
- package/dist/test/mentions-e2e.test.js +261 -0
- package/dist/test/mentions-ledger.test.js +265 -0
- package/dist/test/mentions-listen.test.js +265 -0
- package/dist/test/mentions.test.js +238 -0
- package/dist/test/message-selection.test.js +114 -0
- package/dist/test/mo-glyph.test.js +22 -0
- package/dist/test/model-resolution.test.js +166 -0
- package/dist/test/narrate-validate.test.js +77 -0
- package/dist/test/narrate-wait.test.js +160 -0
- package/dist/test/narrative-format.test.js +219 -0
- package/dist/test/narrative-menu.test.js +137 -0
- package/dist/test/narrative-sort.test.js +75 -0
- package/dist/test/no-pan.test.js +60 -0
- package/dist/test/pane-layout.test.js +153 -0
- package/dist/test/paths.test.js +37 -0
- package/dist/test/payload-inline.test.js +91 -0
- package/dist/test/precache-fonts.test.js +72 -0
- package/dist/test/presence-gate.test.js +440 -0
- package/dist/test/presence.test.js +160 -0
- package/dist/test/read-events.test.js +220 -0
- package/dist/test/remote-meld.test.js +115 -0
- package/dist/test/revive-cli.test.js +93 -0
- package/dist/test/search-floor.test.js +206 -0
- package/dist/test/search-fusion.test.js +168 -0
- package/dist/test/search.test.js +205 -0
- package/dist/test/security.test.js +48 -0
- package/dist/test/selection-wiring.test.js +61 -0
- package/dist/test/session-affinity.test.js +295 -0
- package/dist/test/signal-source.test.js +32 -0
- package/dist/test/socket-account.test.js +268 -0
- package/dist/test/spawn-toml.test.js +72 -0
- package/dist/test/speaker-color.test.js +90 -0
- package/dist/test/tailscale-rebind.test.js +79 -0
- package/dist/test/terminal-cursor.test.js +61 -0
- package/dist/test/terminal-resync.test.js +23 -0
- package/dist/test/thin-cli.test.js +382 -0
- package/dist/test/token-bootstrap.test.js +272 -0
- package/dist/test/token-devices.test.js +587 -0
- package/dist/test/token-lapse.test.js +94 -0
- package/dist/test/token-ring.test.js +188 -0
- package/dist/test/token-rotate-cli.test.js +58 -0
- package/dist/test/token-routes.test.js +95 -0
- package/dist/test/tool-uses.test.js +1006 -0
- package/dist/test/usage-ledger.test.js +126 -0
- package/dist/test/view-url.test.js +581 -0
- package/dist/test/wiki-links.test.js +57 -0
- package/dist/test/wiki-sources.test.js +85 -0
- package/dist/test/wiki-window.test.js +31 -0
- package/dist/test/wiki.test.js +399 -0
- package/dist/test/wordpiece.test.js +68 -0
- package/dist/tls.js +148 -0
- package/dist/tmux.js +202 -0
- package/dist/user-agent.js +46 -0
- package/docker-entrypoint.sh +141 -0
- package/docs/README.md +3 -0
- package/docs/absorb.md +231 -0
- package/docs/cost-ledger.md +125 -0
- package/docs/daemon-api.md +189 -0
- package/docs/diagrams.md +163 -0
- package/docs/doctor.md +36 -0
- package/docs/export-scope.md +69 -0
- package/docs/files-view.md +133 -0
- package/docs/link-previews.md +38 -0
- package/docs/math.md +32 -0
- package/docs/mcp.md +69 -0
- package/docs/memory-search.md +75 -0
- package/docs/mentions.md +101 -0
- package/docs/multi-brane.md +14 -0
- package/docs/passkeys.md +165 -0
- package/docs/presence.md +202 -0
- package/docs/releasing.md +53 -0
- package/docs/rendering-warnings.md +22 -0
- package/docs/request-layer.md +72 -0
- package/docs/selection-store.md +50 -0
- package/docs/session-affinity.md +61 -0
- package/docs/terminal-mirroring.md +211 -0
- package/docs/token-rotation.md +413 -0
- package/docs/view-urls.md +114 -0
- package/docs/web-app.md +23 -0
- package/docs/wiki.md +43 -0
- package/expo/dist/_expo/static/js/web/entry-e56efc1291dca7258ea00b8108b033a4.js +1097 -0
- package/expo/dist/apple-touch-icon.png +0 -0
- package/expo/dist/favicon.svg +3 -0
- package/expo/dist/index.html +177 -0
- package/expo/dist/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/expo/dist/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/expo/dist/katex/katex.min.css +1 -0
- package/expo/dist/manifest.json +16 -0
- package/expo/dist/metadata.json +1 -0
- package/expo/dist/og/membrane.v1.png +0 -0
- package/expo/dist/pdf.min.mjs +28 -0
- package/expo/dist/pdf.worker.min.mjs +28 -0
- package/expo/dist/sw.js +154 -0
- package/package.json +81 -23
- package/protocols/LIVE_loop.md +407 -0
- package/protocols/bebrief.md +41 -0
- package/protocols/digest.md +231 -0
- package/protocols/fly.md +266 -0
- package/protocols/idle.md +81 -0
- package/protocols/keeper.md +829 -0
- package/protocols/markdown.md +80 -0
- package/protocols/memory.md +419 -0
- package/protocols/mentions.md +93 -0
- package/protocols/payloads.md +53 -0
- package/protocols/prelude.md +91 -0
- package/protocols/ramify.md +105 -0
- package/protocols/review.md +356 -0
- package/protocols/rrr.md +232 -0
- package/protocols/scribe.md +429 -0
- package/protocols/summarize.md +203 -0
- package/protocols/twin.md +174 -0
- package/protocols/wiki.md +438 -0
- package/protocols/worker.md +38 -0
- package/wiki/shared/append-only-event-log.md +148 -0
- package/wiki/shared/index.md +48 -0
- package/wiki/shared/owning-your-narratives.md +161 -0
- package/wiki/shared/premature-ontologies.md +435 -0
- package/wiki/shared/sedimentary-superintelligence.md +128 -0
- package/wiki/shared/sequestering-the-narrative.md +143 -0
- package/wiki/shared/why-wikis-work.md +216 -0
- package/.npmignore +0 -2
- package/.travis.yml +0 -5
- package/index.js +0 -8
- package/index.js~ +0 -12
package/protocols/rrr.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# Protocol: rrr
|
|
2
|
+
|
|
3
|
+
`/rrr [branch=main]` puts the running code on what is actually merged.
|
|
4
|
+
Fetch, rebase onto `origin/<branch>`, rebuild, restart.
|
|
5
|
+
|
|
6
|
+
Three letters, four r's:
|
|
7
|
+
|
|
8
|
+
| r | step |
|
|
9
|
+
|---|---|
|
|
10
|
+
| *refetch* | `git fetch origin` — elided from the name, because it's implied |
|
|
11
|
+
| **rebase** | onto `origin/<branch>` |
|
|
12
|
+
| **rebuild** | the project's build |
|
|
13
|
+
| **restart** | whatever long-running process serves that build, if there is one |
|
|
14
|
+
|
|
15
|
+
The first half is the same in every repository. The second half is
|
|
16
|
+
whatever *this* fold's build and process are — read them off the
|
|
17
|
+
project (`package.json` scripts, a `Makefile`, a `justfile`, its
|
|
18
|
+
README) rather than assuming. When the fold is the brane repository
|
|
19
|
+
itself, they are `npm run build` and `brane daemon restart`, and that
|
|
20
|
+
case has enough of its own consequences to get its own section at the
|
|
21
|
+
end of this document.
|
|
22
|
+
|
|
23
|
+
## Why
|
|
24
|
+
|
|
25
|
+
An agent's working tree is a claim about the world; `origin/main` is
|
|
26
|
+
the world. Between them sit merged PRs you never pulled, your own
|
|
27
|
+
commits that were squashed on the way in, and build output compiled
|
|
28
|
+
from neither. `/rrr` collapses the three into one state and puts the
|
|
29
|
+
live process on it, so that what you are about to test is **what has
|
|
30
|
+
actually been merged** rather than what your branch believes.
|
|
31
|
+
|
|
32
|
+
The last step is the one that matters. A build writes files; a
|
|
33
|
+
process that started before the build holds its code in memory. Until
|
|
34
|
+
it is restarted, a green build is a claim about files on disk and
|
|
35
|
+
nothing more.
|
|
36
|
+
|
|
37
|
+
**The operator knows the restart will blink.** On an explicit `/rrr`,
|
|
38
|
+
do not spend a narration warning about the process going down or
|
|
39
|
+
asking whether to proceed; the invocation *is* the consent. Report the
|
|
40
|
+
restart as a step you took, not a risk you weighed.
|
|
41
|
+
|
|
42
|
+
## Restart from the right checkout
|
|
43
|
+
|
|
44
|
+
A restart is only "testing this tree" if the process is started *from*
|
|
45
|
+
this tree. Many restart commands re-exec whatever checkout invoked them
|
|
46
|
+
— so restarting from a worktree does not test the worktree; it installs
|
|
47
|
+
that worktree's build as the process for everyone who shares it, until
|
|
48
|
+
someone restarts from somewhere else.
|
|
49
|
+
|
|
50
|
+
So before step 6, ask where the running process was started from, and
|
|
51
|
+
compare it to `whoami`'s `fold_dir`. If they differ:
|
|
52
|
+
|
|
53
|
+
- **Don't restart from here** unless the operator has said to, knowing
|
|
54
|
+
what it means. It is a wider side effect wearing the costume of a
|
|
55
|
+
local one.
|
|
56
|
+
- You may still do the read-only half — `git fetch origin`, and rebase
|
|
57
|
+
*your own branch* onto `origin/<branch>` if that is what you want.
|
|
58
|
+
That is ordinary work, not `/rrr`.
|
|
59
|
+
- If what you need is the process on merged code, say so and let the
|
|
60
|
+
operator run `/rrr` in the checkout it runs from, or ask for
|
|
61
|
+
permission to walk over to it. Then come back.
|
|
62
|
+
|
|
63
|
+
## Steps
|
|
64
|
+
|
|
65
|
+
Narrate as you go — each step's real output, not a plan restated. A
|
|
66
|
+
`/rrr` that reports "rebased, rebuilt, restarted" without ever showing
|
|
67
|
+
what git and the build said is indistinguishable from one that did
|
|
68
|
+
nothing.
|
|
69
|
+
|
|
70
|
+
**1. Fetch.** `git fetch origin` — or `git fetch origin <branch>`.
|
|
71
|
+
This comes first because the next step is a question about the
|
|
72
|
+
*target*, and you cannot ask it before you have one.
|
|
73
|
+
|
|
74
|
+
**2. Take stock of the tree.** `git status --porcelain`, and then, for
|
|
75
|
+
each path it names, the question that actually matters:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
git show origin/<branch>:<path> | diff - <path>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The question is **not** "is the tree dirty?" — that is tidiness. It is
|
|
82
|
+
**"does this tree hold bytes that exist nowhere else?"** Dirt is only
|
|
83
|
+
dangerous when it is the sole copy of something.
|
|
84
|
+
|
|
85
|
+
- **Empty diff — a duplicate.** The file already matches where you are
|
|
86
|
+
going; the sync will not change it. `git add` it and continue. That
|
|
87
|
+
is not a workaround: git compares the *index* against the target, so
|
|
88
|
+
an entry that already equals the incoming content applies cleanly and
|
|
89
|
+
the file lands tracked and clean. An untracked file matching an
|
|
90
|
+
incoming *new* file is the same case and takes the same `git add`.
|
|
91
|
+
- **Non-empty diff, or the path doesn't exist upstream — real work.**
|
|
92
|
+
**Stop here and report it.** Do not stash, do not `git checkout --`,
|
|
93
|
+
do not `git clean`, do not `git rebase --skip` your way past a
|
|
94
|
+
conflict. The golden rule at the head of this document covers
|
|
95
|
+
uncommitted work, which is the most easily destroyed artifact in the
|
|
96
|
+
repository and the only one with no copy anywhere.
|
|
97
|
+
- **Mid-conflict** (`UU`, a `rebase-merge/` directory) — stop
|
|
98
|
+
regardless. Someone's resolution is in progress.
|
|
99
|
+
|
|
100
|
+
Untracked files unrelated to the sync — scratch scripts, tarballs,
|
|
101
|
+
build droppings — are neither; leave them in place, say what they are,
|
|
102
|
+
and continue.
|
|
103
|
+
|
|
104
|
+
The duplicate case is worth spelling out because it is the *common*
|
|
105
|
+
one, not an edge: you merged your own PR, so your working copies are
|
|
106
|
+
copies of the destination. Treating that as a blocker stops the run
|
|
107
|
+
over files that hold no information — and a guard that fires on the
|
|
108
|
+
ordinary case is one people learn to route around, which is how the
|
|
109
|
+
guard stops protecting the case that matters.
|
|
110
|
+
|
|
111
|
+
**3. Switch and rebase.**
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
git checkout <branch> # default: main
|
|
115
|
+
git rebase origin/<branch>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
On a checkout of `main` that has no local commits this is a
|
|
119
|
+
fast-forward and says so. If the rebase **conflicts**, stop: narrate
|
|
120
|
+
the conflicting paths and the operator decides. Do not resolve
|
|
121
|
+
conflicts inside `/rrr` — you were asked to sync, and a conflict means
|
|
122
|
+
the sync is a question rather than a mechanism.
|
|
123
|
+
|
|
124
|
+
**4. Reinstall if the dependencies moved.** Note the pre-rebase commit
|
|
125
|
+
(`git rev-parse HEAD`) before step 3, then afterwards ask what actually
|
|
126
|
+
moved among the project's lockfiles and anything that patches
|
|
127
|
+
installed packages:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
git diff --name-only <old>..HEAD -- <lockfiles> <patch dirs>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
If any of them changed, run the matching install. A repository can
|
|
134
|
+
hold more than one independent package tree — a root and a sub-app,
|
|
135
|
+
each with its own lockfile and `node_modules` — and a top-level build
|
|
136
|
+
that *runs* the sub-app's build without installing for it; check each
|
|
137
|
+
tree, not just the root. Patch directories (`patch-package`,
|
|
138
|
+
`patches/`) belong in the list because a changed patch rewrites code
|
|
139
|
+
inside an installed package and shows up in **no** lockfile at all, so
|
|
140
|
+
it is invisible to the check everyone thinks to run.
|
|
141
|
+
|
|
142
|
+
Skipping this is not a build failure, which is what makes it worth a
|
|
143
|
+
step. A stale dependency tree usually compiles and then misbehaves at
|
|
144
|
+
runtime, and the hour goes to debugging the code that was merged rather
|
|
145
|
+
than the install that wasn't. When in doubt, install everything — it
|
|
146
|
+
is seconds when nothing changed.
|
|
147
|
+
|
|
148
|
+
**5. Rebuild.** The project's full build — not just its typecheck, if
|
|
149
|
+
the two differ, and not just one half of a multi-part build: a server
|
|
150
|
+
compiled against a stale client bundle presents as a UI bug rather
|
|
151
|
+
than a build one. If the build fails, **stop and report the error**;
|
|
152
|
+
do not restart onto half-written output.
|
|
153
|
+
|
|
154
|
+
**6. Restart.** The process that serves the build, with whatever
|
|
155
|
+
command the project uses for it. Mind the checkout question above.
|
|
156
|
+
|
|
157
|
+
**7. Confirm.** Check the process actually came back on new code —
|
|
158
|
+
its pid changed, it is alive, its reported version or start time
|
|
159
|
+
moved. A restart that silently failed leaves the old process running
|
|
160
|
+
and every subsequent test measuring the old code.
|
|
161
|
+
|
|
162
|
+
## Afterwards
|
|
163
|
+
|
|
164
|
+
Say what changed, concretely: the commit range the rebase brought in
|
|
165
|
+
(`git log --oneline <old>..HEAD`), whether the build was clean, the
|
|
166
|
+
new pid. That list is the point of the exercise — it is the answer to
|
|
167
|
+
"what am I now testing?"
|
|
168
|
+
|
|
169
|
+
Then return to the LIVE loop and `listen`. `/rrr` is preparation; the
|
|
170
|
+
operator usually has something they wanted to test *on* merged code,
|
|
171
|
+
and that instruction is the next signal.
|
|
172
|
+
|
|
173
|
+
## In the brane repository itself
|
|
174
|
+
|
|
175
|
+
Everything below applies only when the fold **is** the brane checkout
|
|
176
|
+
— the one whose `dist/` the daemon is running. In any other project,
|
|
177
|
+
none of it does.
|
|
178
|
+
|
|
179
|
+
**The four r's, concretely.** Rebuild is `npm run build` — `tsc` plus
|
|
180
|
+
the Expo web export. Not `npx tsc` alone: that leaves `expo/dist/`
|
|
181
|
+
stale, so the daemon serves the *old* app bundle over the new server.
|
|
182
|
+
Restart is `brane daemon restart`; it preserves port and token, so
|
|
183
|
+
existing links and QR codes keep working. Confirm with `brane daemon
|
|
184
|
+
status` and check the pid moved.
|
|
185
|
+
|
|
186
|
+
**The daemon is one process per machine, and it restarts from whichever
|
|
187
|
+
checkout invoked the command** — `brane daemon restart` re-spawns
|
|
188
|
+
`process.argv[1]`. That is the "restart from the right checkout" rule
|
|
189
|
+
above at its sharpest: a restart from a worktree installs that
|
|
190
|
+
worktree's build as the daemon for every other agent's MCP bridge,
|
|
191
|
+
every open phone, and every terminal mirror. `/rrr` therefore belongs
|
|
192
|
+
in the checkout the daemon already runs from; confirm with `whoami`'s
|
|
193
|
+
`fold_dir` against the running daemon rather than assuming.
|
|
194
|
+
|
|
195
|
+
**What the blink is.** Every agent's MCP bridge drops, the app
|
|
196
|
+
reconnects, terminal mirrors resync — a few seconds, and none of it is
|
|
197
|
+
news to the operator.
|
|
198
|
+
|
|
199
|
+
**Two package trees.** `package-lock.json` at the root and
|
|
200
|
+
`expo/package-lock.json`, each with its own `node_modules`, not a
|
|
201
|
+
workspace. `npm run build` *runs* the Expo build (`npm run build:web
|
|
202
|
+
--prefix expo`) but never installs for it. So step 4's diff is:
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
git diff --name-only <old>..HEAD -- \
|
|
206
|
+
package-lock.json expo/package-lock.json expo/patches
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- root lockfile → `npm i`
|
|
210
|
+
- `expo/package-lock.json` **or** `expo/patches/` → `(cd expo; npm i)`
|
|
211
|
+
- both, or you'd rather not read the diff → `npm i && (cd expo; npm i)`
|
|
212
|
+
|
|
213
|
+
`expo/patches/` is there because `expo/package.json`'s `postinstall`
|
|
214
|
+
runs `patch-package`.
|
|
215
|
+
|
|
216
|
+
**Your own bridge goes down with it.** You are restarting the daemon
|
|
217
|
+
your MCP bridge is connected to. The bridge reconnects on its own with
|
|
218
|
+
backoff, but in the window around the restart a brane call in flight
|
|
219
|
+
comes back `daemon connection lost (reconnecting — please retry)` and
|
|
220
|
+
a parked `listen` is answered and dropped. **Retry the call.** Once.
|
|
221
|
+
That error is the restart working, not the restart failing — and it is
|
|
222
|
+
not something to narrate an alarm about. Only if calls are still
|
|
223
|
+
failing after several seconds of retries has something actually gone
|
|
224
|
+
wrong; then report it with the real error text, and check `brane
|
|
225
|
+
daemon logs` before concluding anything.
|
|
226
|
+
|
|
227
|
+
**Protocol changes need no `/rrr`.** The daemon reads `protocols/`
|
|
228
|
+
from disk on every `read_protocol`, so a protocol edit is live the
|
|
229
|
+
moment it is written. Same for `wiki/`. If a rebase brought in only
|
|
230
|
+
markdown under those directories, the rebuild and restart are honest
|
|
231
|
+
work but they are not what made the change take effect — say so rather
|
|
232
|
+
than implying the restart was load-bearing.
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# /scribe [target]
|
|
2
|
+
|
|
3
|
+
Take human dictation and render it faithfully into a progressively more
|
|
4
|
+
complete document, without embellishment. The operator dictates; the
|
|
5
|
+
scribe commits only what the operator **endorses**, in the operator's own
|
|
6
|
+
voice, and nothing more. The scribe is a **faithful recorder, not an
|
|
7
|
+
author** — its fidelity to the source *is* the job.
|
|
8
|
+
|
|
9
|
+
`/scribe` is the near-mirror of [`/wiki`](wiki.md): the wiki forbids the
|
|
10
|
+
agent from inventing *concepts*; the scribe forbids it from inventing
|
|
11
|
+
*words*. Anything on the page the operator did not endorse is a defect.
|
|
12
|
+
|
|
13
|
+
The endgame is a fully voice-driven tool — speech-to-text in,
|
|
14
|
+
text-to-speech read-back out — so every rule holds when the operator
|
|
15
|
+
can't see the screen and must trust their ears. That makes fidelity
|
|
16
|
+
load-bearing, not aspirational.
|
|
17
|
+
|
|
18
|
+
## Prime directive
|
|
19
|
+
|
|
20
|
+
**No content enters the document except as a faithful rendering of
|
|
21
|
+
something the operator endorsed** — composed, pasted, or authorized by
|
|
22
|
+
reference (see *Provenance*). The scribe contributes no substance of its
|
|
23
|
+
own: no invented sentences, no connective tissue, no "the author notes
|
|
24
|
+
that…", no polishing a rough idea, no filling a gap with a guess. When
|
|
25
|
+
tempted to add, it raises an **open question** and waits.
|
|
26
|
+
|
|
27
|
+
The page is in the **operator's voice**, their phrasing preserved. The
|
|
28
|
+
scribe's own voice appears only in read-backs and open questions, never
|
|
29
|
+
in document prose.
|
|
30
|
+
|
|
31
|
+
## Target, up front
|
|
32
|
+
|
|
33
|
+
A session **begins by fixing its destination** — the operator names the
|
|
34
|
+
artifact (usually a markdown file) before any dictation is committed:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
/scribe spec.md
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- **File doesn't exist** → the scribe creates it and starts an empty
|
|
41
|
+
manifest (see *The ledger*).
|
|
42
|
+
- **File exists** → the scribe **adopts** it: its current content becomes
|
|
43
|
+
one or more `baseline` fragments — preserved and rendered, but with no
|
|
44
|
+
endorsement chain (a later `/notary` pass marks baseline ungrounded).
|
|
45
|
+
The scribe never claims baseline content as human-authored.
|
|
46
|
+
- **No target set** → the scribe's first act is to ask for one; nothing
|
|
47
|
+
is committed until a destination exists.
|
|
48
|
+
|
|
49
|
+
The target is **sticky**: dictation lands there until the operator
|
|
50
|
+
redirects (`/scribe other.md`) or exits.
|
|
51
|
+
|
|
52
|
+
## Latched session
|
|
53
|
+
|
|
54
|
+
Dictation is continuous — the operator won't prefix every sentence,
|
|
55
|
+
least of all by voice — so the scribe **latches**:
|
|
56
|
+
|
|
57
|
+
- `/scribe <target>` opens a resident session.
|
|
58
|
+
- While latched, **every** `human_signal` is handled by the scribe (as
|
|
59
|
+
prose, instruction, query, or correction), not as a general LIVE-loop
|
|
60
|
+
request.
|
|
61
|
+
- `/scribe stop` closes it; the scribe confirms and returns to the
|
|
62
|
+
ordinary loop.
|
|
63
|
+
|
|
64
|
+
If something plainly outside the writing task arrives while latched, the
|
|
65
|
+
scribe raises an open question ("didn't sound like dictation — step out
|
|
66
|
+
of the session?") rather than silently acting or transcribing.
|
|
67
|
+
|
|
68
|
+
## Channels: four kinds of utterance
|
|
69
|
+
|
|
70
|
+
Every latched `human_signal` is one of four things, never bleeding
|
|
71
|
+
together:
|
|
72
|
+
|
|
73
|
+
1. **Prose** — content to render, in the operator's voice.
|
|
74
|
+
2. **Instruction** — a directive about the document's *shape*: "intro
|
|
75
|
+
goes last," "keep §3 before §2," "put the pricing bit under §2." May
|
|
76
|
+
be **standing** or one-off. Changes fragment *metadata* (placement,
|
|
77
|
+
ordering), never fragment *text*.
|
|
78
|
+
3. **Query** — a question *about* the document that changes nothing:
|
|
79
|
+
"read me back §2," "word count?" Answered from the render; no change.
|
|
80
|
+
4. **Correction / retraction** — a change to what's there: an in-flight
|
|
81
|
+
fix ("no, make that fifteen percent") **supersedes** a fragment; a
|
|
82
|
+
retraction ("strike that") **retracts** one.
|
|
83
|
+
|
|
84
|
+
**Disambiguation is hybrid:** infer the channel from phrasing by default;
|
|
85
|
+
reserved mode-words override when the operator wants certainty (`note:` /
|
|
86
|
+
`instruction:` mark an instruction, `scribe:` addresses the scribe,
|
|
87
|
+
`verbatim:` forces prose — for dictating text that *itself* begins with a
|
|
88
|
+
mode-word, e.g. writing documentation about scribe; plain speech is
|
|
89
|
+
prose); the **read-back is the safety net** — a misclassification is
|
|
90
|
+
caught on the next breath. When genuinely uncertain *and* the guess would
|
|
91
|
+
change the document, the scribe **asks**. A wrong silent guess is exactly
|
|
92
|
+
the embellishment this protocol prevents.
|
|
93
|
+
|
|
94
|
+
## The per-utterance loop
|
|
95
|
+
|
|
96
|
+
For **every** latched `human_signal`, in order:
|
|
97
|
+
|
|
98
|
+
1. **Classify** the channel (prose / instruction / query / correction).
|
|
99
|
+
2. **Apply the fidelity licence** and create or modify **fragment(s)** in
|
|
100
|
+
the manifest — never edit document text directly.
|
|
101
|
+
3. **Re-render** the target wholesale from the manifest (see *Projection*).
|
|
102
|
+
4. **Verify** the render equals a fresh recompute from the manifest,
|
|
103
|
+
byte-for-byte; on mismatch, **fail closed** — re-render, do not proceed.
|
|
104
|
+
5. **Read back** the fragment delta and cite the endorsing seq.
|
|
105
|
+
6. **Update `meta.summary`** to `Scribe: <target> — §<current section>`.
|
|
106
|
+
|
|
107
|
+
Queries touch neither manifest nor file — answer from the current render
|
|
108
|
+
and read back. Everything else runs the full loop.
|
|
109
|
+
|
|
110
|
+
## The ledger: fragment, manifest, projection
|
|
111
|
+
|
|
112
|
+
The document is **not the store** — it is a *projection*. The store is a
|
|
113
|
+
ledger of endorsed fragments; the file is regenerated from it on every
|
|
114
|
+
change. Nothing is ever edited in place, so nothing untouched can be
|
|
115
|
+
silently relexed: *the document is a projection; the log is the
|
|
116
|
+
notarized ledger.*
|
|
117
|
+
|
|
118
|
+
**Fragment — the unit of record.** Each endorsed utterance yields at most
|
|
119
|
+
one fragment: the operator's words, verbatim after the fidelity licence.
|
|
120
|
+
A fragment carries:
|
|
121
|
+
|
|
122
|
+
- `id` — a stable handle, `f<seq>` of the endorsing signal (`baseline-N`
|
|
123
|
+
for adopted content).
|
|
124
|
+
- `endorse` — the endorsing `human_signal` `nid:seq` (`null` for
|
|
125
|
+
baseline).
|
|
126
|
+
- `origin` — for adopted-by-reference passages, the `nid:seq` the words
|
|
127
|
+
came from; else `null`. Two-coordinate provenance: *who authorized*
|
|
128
|
+
distinct from *where the words came from*.
|
|
129
|
+
- `section` — the placement label (which outline section it belongs to);
|
|
130
|
+
`null` ⇒ appended at document end.
|
|
131
|
+
- `status` — `active` · `superseded:<id>` · `retracted` · `baseline`.
|
|
132
|
+
- `text` — the verbatim content.
|
|
133
|
+
|
|
134
|
+
**Manifest — the working store.** A sidecar next to the target:
|
|
135
|
+
`<target>.scribe.json`. It holds the ordered section outline, every
|
|
136
|
+
fragment record (**never deleted** — only its `status` changes), standing
|
|
137
|
+
instructions, open questions, and the hash of the last render. The event
|
|
138
|
+
log remains ground truth for audit; the manifest is the machine-checkable
|
|
139
|
+
index into it. Maintain it with ordinary file tools until a future
|
|
140
|
+
`brane scribe` command owns it.
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"target": "spec.md",
|
|
145
|
+
"sections": ["Overview", "Pricing", "Deployment"],
|
|
146
|
+
"fragments": [
|
|
147
|
+
{ "id": "f7", "endorse": "claude-4anserzq:7", "origin": null,
|
|
148
|
+
"section": "Pricing", "status": "active",
|
|
149
|
+
"text": "Pricing starts at fifteen percent of contract value." }
|
|
150
|
+
],
|
|
151
|
+
"standing": ["Introduction goes last."],
|
|
152
|
+
"questions": [
|
|
153
|
+
{ "id": "q9", "kind": "hole", "text": "§Deployment named, not yet dictated." }
|
|
154
|
+
],
|
|
155
|
+
"render_hash": "sha256:…"
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Projection — the document is rendered, never edited.** On every change,
|
|
160
|
+
regenerate the target `.md` wholesale: section headings in outline order,
|
|
161
|
+
then each section's `active` fragments in manifest order, then the
|
|
162
|
+
scribe-notes block. Rendering is **mechanical copying** — the agent
|
|
163
|
+
assembles the file *by reading `text` out of the manifest*, never by
|
|
164
|
+
recalling prose from context. Writing (overwriting) the target is the
|
|
165
|
+
*render mechanism* and is expected; the ledger, not the file, is the thing
|
|
166
|
+
never rewritten from memory.
|
|
167
|
+
|
|
168
|
+
**Render verification — the fail-closed gate.** The render is a *pure
|
|
169
|
+
function of the manifest* — headings from `sections`, each section's
|
|
170
|
+
`active` fragments in order, then the notes block. So verification is
|
|
171
|
+
**deterministic equality**: recompute the expected render from the
|
|
172
|
+
manifest and require it to match the file on disk **byte-for-byte**. Any
|
|
173
|
+
mismatch ⇒ re-render; never accept a render that doesn't match. This is
|
|
174
|
+
strictly stronger than the old snapshot→diff gate — one check proves at
|
|
175
|
+
once that every fragment is present and faithful, that **nothing
|
|
176
|
+
unendorsed was inserted between fragments**, and that the order is
|
|
177
|
+
correct. And because the check is a pure recompute, a dumb tool can run
|
|
178
|
+
it — a future `brane scribe render --check`, the notary, or the operator
|
|
179
|
+
— so fidelity never rests on the agent's discipline.
|
|
180
|
+
|
|
181
|
+
**Placement — no cursor.** The operator never manages an insertion point.
|
|
182
|
+
A fragment's `section` is set from the section the operator most recently
|
|
183
|
+
named; absent any, it appends at document end. "Put the pricing bit under
|
|
184
|
+
§2" is a **metadata change** (set `section`) plus a re-render — no text
|
|
185
|
+
surgery. The scribe never *guesses* placement: ambiguous placement stays
|
|
186
|
+
an open question. Directed placement is faithful; invented placement is
|
|
187
|
+
embellishment.
|
|
188
|
+
|
|
189
|
+
**Corrections and retractions.** "No wait, fifteen percent" → a **new**
|
|
190
|
+
fragment (endorsed by the correcting seq) whose `status` supersedes the
|
|
191
|
+
old one; the superseded record stays in the manifest, absent from the
|
|
192
|
+
render. "Strike that" → set the fragment's `status` to `retracted` (text
|
|
193
|
+
preserved in the manifest, absent from the render). No in-place text edit
|
|
194
|
+
exists anywhere in this protocol.
|
|
195
|
+
|
|
196
|
+
**Drift guard.** Before each render, compare the on-disk file to the
|
|
197
|
+
manifest's `render_hash`. A mismatch means the file was hand-edited since
|
|
198
|
+
the last render. **Never clobber silently:** raise an open question. If
|
|
199
|
+
the operator endorses the drift, adopt it as a fragment endorsed by that
|
|
200
|
+
signal; otherwise the next render restores the manifest's truth.
|
|
201
|
+
|
|
202
|
+
## Fidelity line
|
|
203
|
+
|
|
204
|
+
Faithful is not literal-to-a-fault; speech carries noise the operator
|
|
205
|
+
doesn't intend as content. The licence is narrow and fixed:
|
|
206
|
+
|
|
207
|
+
**Permitted** (faithful to intent): strip disfluencies ("um," false
|
|
208
|
+
starts, stumbles); honor explicit self-corrections (commit the corrected
|
|
209
|
+
form, not the abandoned one); normalize mechanical surface (casing,
|
|
210
|
+
obvious punctuation, implied paragraph breaks).
|
|
211
|
+
|
|
212
|
+
**Forbidden** (embellishment): adding, sharpening, or "improving" any
|
|
213
|
+
substantive word; reordering beyond an explicit instruction; resolving an
|
|
214
|
+
ambiguity by guessing intent; expanding a pronoun or reference unless its
|
|
215
|
+
referent is unambiguous in the immediate dictation — otherwise raise an
|
|
216
|
+
open question.
|
|
217
|
+
|
|
218
|
+
Every substantive word is preserved. When in doubt, preserve and ask.
|
|
219
|
+
|
|
220
|
+
## Scribe notes: holes and standing instructions
|
|
221
|
+
|
|
222
|
+
Standing instructions and open questions aren't prose but belong *with*
|
|
223
|
+
the document. They live **only in the manifest** (`standing`,
|
|
224
|
+
`questions`) and are **rendered** into a visible, scribe-owned block at
|
|
225
|
+
the foot of the file — one source of truth, so the block and any inline
|
|
226
|
+
markers can never drift apart:
|
|
227
|
+
|
|
228
|
+
```markdown
|
|
229
|
+
<!-- SCRIBE:BEGIN -->
|
|
230
|
+
## Scribe notes
|
|
231
|
+
**Standing instructions**
|
|
232
|
+
- Introduction goes last.
|
|
233
|
+
**Open questions**
|
|
234
|
+
- [order?] Pricing paragraph under §2 or its own section?
|
|
235
|
+
- [hole] §Deployment named but not yet dictated.
|
|
236
|
+
<!-- SCRIBE:END -->
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
- **Holes** (sections named but not dictated) and **debates** (order,
|
|
240
|
+
referent, ambiguity) are `questions` entries; the render surfaces each,
|
|
241
|
+
including any inline `> [SCRIBE: …]` marker at its location.
|
|
242
|
+
- The scribe **never resolves an open question itself** — that would be
|
|
243
|
+
authoring. It waits for the operator, then applies the resolution
|
|
244
|
+
(a manifest change + re-render) and drops the `questions` entry.
|
|
245
|
+
- **Standing instructions apply retroactively.** "Intro goes last" sets
|
|
246
|
+
placement metadata now, is read back, and is recorded in `standing` to
|
|
247
|
+
govern future work.
|
|
248
|
+
|
|
249
|
+
## Read-back: the operator's only mirror
|
|
250
|
+
|
|
251
|
+
In a voice-only session the read-back is the *sole* way to catch an
|
|
252
|
+
embellishment, so it is **mandatory** and **derived from the fragment
|
|
253
|
+
delta** (what the utterance created, superseded, or retracted), never from
|
|
254
|
+
recollection of intent:
|
|
255
|
+
|
|
256
|
+
- **Cadence:** one concise read-back **per `human_signal`** — what
|
|
257
|
+
changed, plus any open question raised. Full-document read-back only on
|
|
258
|
+
request.
|
|
259
|
+
- **Form (two-part):** a **speakable sentence** first — TTS reads this
|
|
260
|
+
("Added to §Pricing; one question: before or after the terms?") —
|
|
261
|
+
followed by the committed **fragment text verbatim** in a fenced block,
|
|
262
|
+
the literal audit record:
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
Pricing starts at fifteen percent of contract value.
|
|
266
|
+
```
|
|
267
|
+
- **Content is literal, never a paraphrase.** Cite the endorsing seq via
|
|
268
|
+
`re:` and in text; for adopted content also name the `origin` seq.
|
|
269
|
+
|
|
270
|
+
## Provenance: every fragment carries a human endorsement
|
|
271
|
+
|
|
272
|
+
The document is built so a later, independent
|
|
273
|
+
[`/notary`](#the-notary-a-separable-follow-on) pass can prove **every
|
|
274
|
+
fragment was endorsed by the operator**, and quantify *how*. Two brane
|
|
275
|
+
guarantees make it possible:
|
|
276
|
+
|
|
277
|
+
- **`source` is stamped server-side and cannot be spoofed** — a
|
|
278
|
+
`human_signal` is provably operator-originated.
|
|
279
|
+
- **`seq` is monotonic and append-only** — `nid:seq` is an immutable
|
|
280
|
+
coordinate for a specific human utterance.
|
|
281
|
+
|
|
282
|
+
The scribe's obligations:
|
|
283
|
+
|
|
284
|
+
1. **Admission rule.** Every fragment must carry an **operator
|
|
285
|
+
endorsement** delivered through a `human_signal`. Endorsement is read
|
|
286
|
+
*maximally* — composing words fresh, pasting them, **or authorizing a
|
|
287
|
+
previously discussed passage by brief reference** ("add the pricing
|
|
288
|
+
paragraph the agent drafted"). A reference is dictation in the
|
|
289
|
+
abstract: the operator adopts an *identified* passage without
|
|
290
|
+
re-uttering it. Forbidden is only the *scribe* pulling agent content
|
|
291
|
+
in **on its own initiative**. When admitting by reference: the
|
|
292
|
+
referent must be **unambiguous** (resolve to a specific `nid:seq`, else
|
|
293
|
+
raise an open question — *which* passage?), and the retrieved passage
|
|
294
|
+
is **rendered faithfully** (copied into the fragment `text`, not
|
|
295
|
+
rewritten or "improved").
|
|
296
|
+
2. **Citation.** Each committing read-back cites the **endorsing
|
|
297
|
+
`human_signal` seq** (the fragment's `endorse`, via `re:` and in text).
|
|
298
|
+
For content admitted by reference, it *also* names the fragment's
|
|
299
|
+
`origin` seq — distinguishing *where the words came from* from *who
|
|
300
|
+
authorized them*, which makes the retrieval independently auditable.
|
|
301
|
+
3. **Grain.** Provenance is tracked per **fragment**. Reorders and
|
|
302
|
+
re-placements move fragments without changing their `text`, so
|
|
303
|
+
provenance rides along untouched.
|
|
304
|
+
|
|
305
|
+
The **canonical store is the event log**, not the document, and not the
|
|
306
|
+
manifest — the manifest is a convenience index and the document a
|
|
307
|
+
projection. The spoof-proof record is the chain of
|
|
308
|
+
`human_signal → citing read-back` events.
|
|
309
|
+
|
|
310
|
+
### What the chain proves: endorsement, not origination
|
|
311
|
+
|
|
312
|
+
Brane witnesses the **channel**, and that is enough. What passes through
|
|
313
|
+
the `human_signal` channel is, by that act, **adopted by the operator as
|
|
314
|
+
their own** — composed, recalled, or pasted alike. Copy-paste is **not
|
|
315
|
+
laundering and not discouraged**: sending something through the human
|
|
316
|
+
channel *is* the decision that "this is what I would have said." The chain
|
|
317
|
+
proves *every fragment was endorsed and faithfully rendered without the
|
|
318
|
+
agent adding anything unendorsed.* It does not prove where the operator's
|
|
319
|
+
ideas came from — **origination is unmeasurable and beside the point;
|
|
320
|
+
endorsement is what authorship has always meant.** A signature never
|
|
321
|
+
certified you originated the language, only that you adopted it.
|
|
322
|
+
|
|
323
|
+
The trust model is asymmetric **by design**: the system **distrusts the
|
|
324
|
+
agent** (fenced by the admission rule and the render-verification gate)
|
|
325
|
+
and **trusts the operator** (their endorsement is definitional). If you
|
|
326
|
+
wouldn't trust the operator's endorsement, no provenance system helps —
|
|
327
|
+
they're the authoring principal, not a party under audit.
|
|
328
|
+
|
|
329
|
+
So the notary's core metric is a **three-way split**, not a single
|
|
330
|
+
"endorsed fraction":
|
|
331
|
+
|
|
332
|
+
- **composed** — the operator supplied the words;
|
|
333
|
+
- **adopted** — the operator authorized an agent-originated passage by
|
|
334
|
+
reference (endorsed, not their words);
|
|
335
|
+
- **unendorsed** — baseline, or a fragment added in violation of the
|
|
336
|
+
admission rule (no endorsement).
|
|
337
|
+
|
|
338
|
+
"Endorsed" alone isn't the discriminator: an operator could authorize a
|
|
339
|
+
whole agent draft by reference — 100% endorsed, 0% composed, fully
|
|
340
|
+
legitimate but not the same as one they wrote. **Composed vs. adopted** is
|
|
341
|
+
what carries weight; ghostwriting surfaces as low-composed or
|
|
342
|
+
high-unendorsed, never as composed. This is the defensible reading of
|
|
343
|
+
"prove exactly how much of it is yours": your *words* (composed), your
|
|
344
|
+
*choices* (adopted), and what is *neither* (unendorsed).
|
|
345
|
+
|
|
346
|
+
## The notary: a separable follow-on
|
|
347
|
+
|
|
348
|
+
Notarization — *attesting* the chain holds — is a **different job** from
|
|
349
|
+
authoring, and wants to be structurally independent: a notary who wrote
|
|
350
|
+
the document is a weak notary. The scribe's citation discipline is the
|
|
351
|
+
evidence base a future `/notary` pass consumes to emit a
|
|
352
|
+
fragment-by-fragment attestation and the composed/adopted/unendorsed
|
|
353
|
+
split. The scribe lays the rails; it does not self-attest. `/notary`'s
|
|
354
|
+
own protocol is a follow-on, not part of this document.
|
|
355
|
+
|
|
356
|
+
## Skill vs. protocol — what Brane adds
|
|
357
|
+
|
|
358
|
+
Most of this document is portable: the behavioral spec (fidelity line,
|
|
359
|
+
channel-sorting, ledger discipline, open-question reflex) is
|
|
360
|
+
agent-interpreted prose that could live as a harness *skill*
|
|
361
|
+
(`.claude/skills/scribe.md`). That part is **not Brane-specific**.
|
|
362
|
+
|
|
363
|
+
Brane's irreducible contribution is **evidence, not behavior**: an
|
|
364
|
+
authority-stamped boundary between human and machine content. A skill's
|
|
365
|
+
only record is its own agent's transcript — single-party, ephemeral,
|
|
366
|
+
certifying nothing about which bytes were human; a process cannot
|
|
367
|
+
notarize its own inputs. Brane's log can, because `source` is stamped by
|
|
368
|
+
a party neither operator nor agent controls, and the log is append-only
|
|
369
|
+
and independently re-verifiable.
|
|
370
|
+
|
|
371
|
+
Scoping:
|
|
372
|
+
|
|
373
|
+
- **No provenance proof needed** → a `/scribe` *skill* is equivalent and
|
|
374
|
+
simpler. Prefer it.
|
|
375
|
+
- **A provable human/AI split matters** — "no reliance on AI" (a fully
|
|
376
|
+
*composed* document) or honest disclosure of what was *adopted* → only
|
|
377
|
+
the Brane substrate delivers it.
|
|
378
|
+
|
|
379
|
+
The slogan: **"write with agent assistance — then prove exactly how much
|
|
380
|
+
of it is yours."** Read "yours" as *endorsed by you*. In one line: **the
|
|
381
|
+
skill gives you *faithful*; the log gives you *provable*.**
|
|
382
|
+
|
|
383
|
+
## Recovery
|
|
384
|
+
|
|
385
|
+
The manifest plus the event log are the **complete** session state — the
|
|
386
|
+
latch, target, ledger, and open questions all persist outside agent
|
|
387
|
+
context. After compaction or a revive:
|
|
388
|
+
|
|
389
|
+
1. `whoami`, then `listen` with `tail` to reload recent context.
|
|
390
|
+
2. Scan back for the most recent `/scribe <target>`; if it has no
|
|
391
|
+
matching `/scribe stop`, the **latch is still on** and `<target>` is
|
|
392
|
+
the sticky destination.
|
|
393
|
+
3. Reload `<target>.scribe.json` — it *is* the working state; re-render
|
|
394
|
+
from it and verify. Nothing is lost.
|
|
395
|
+
4. If the current section is uncertain, read back the tail and **confirm
|
|
396
|
+
with the operator** rather than guess.
|
|
397
|
+
|
|
398
|
+
## Golden rule
|
|
399
|
+
|
|
400
|
+
The scribe **never deletes files, git history, or any artifact** on its
|
|
401
|
+
own. Dictated *retraction* ("strike that sentence") sets a fragment's
|
|
402
|
+
`status` to `retracted` — the text leaves the render but stays in the
|
|
403
|
+
manifest, and the retraction command is itself the `human_signal` of
|
|
404
|
+
record — so the file and everything around it are never removed. Prefer
|
|
405
|
+
`cp` over `mv`; if something seems to need deletion, surface it to the
|
|
406
|
+
operator. See /prelude's Golden Rule.
|
|
407
|
+
|
|
408
|
+
## Quick reference
|
|
409
|
+
|
|
410
|
+
| Operator utterance | Channel | Manifest operation |
|
|
411
|
+
|---|---|---|
|
|
412
|
+
| Plain speech | Prose (composed) | Append `active` fragment, cite endorse seq |
|
|
413
|
+
| "add the pricing bit we discussed" | Prose (adopted by reference) | Append fragment with `origin`, cite endorse + origin |
|
|
414
|
+
| "intro goes last" | Instruction (standing) | Set placement, record in `standing`, re-render |
|
|
415
|
+
| "put the pricing bit under §2" | Instruction (placement) | Set fragment `section`, re-render |
|
|
416
|
+
| "read me back §2," "word count?" | Query | None — answer from render |
|
|
417
|
+
| "no wait, X" | Correction | New fragment supersedes prior, re-render |
|
|
418
|
+
| "strike that" | Retraction | Set `status: retracted`, re-render |
|
|
419
|
+
| Referent or placement unclear | (open question) | Add `questions` entry, wait |
|
|
420
|
+
| `/scribe stop` | Session control | None — closes session |
|
|
421
|
+
|
|
422
|
+
## Related protocols
|
|
423
|
+
|
|
424
|
+
- **[LIVE_loop](LIVE_loop.md)** — the loop this runs inside; source of the
|
|
425
|
+
`human_signal` guarantees provenance depends on.
|
|
426
|
+
- **[wiki](wiki.md)** — sibling faithful-rendering protocol; shares the
|
|
427
|
+
fidelity and provenance disciplines.
|
|
428
|
+
- **[review](review.md)** — precedent for keeping verification independent
|
|
429
|
+
of production (the scribe/notary split).
|