Skip to content

Commit a8d9e55

Browse files
forge/AGENT.md: document the two-channel live-data + rolling-mark pattern
Ties together the ephemeral tier, sparseMarks, and mirror subscribers into one recipe: an ephemeral channel (real-time, no cost) alongside a periodic super-commit channel (sparse-marked, one tx/period), with the hard-won note that real-time latency is the relay you choose (co-locate a relay you control; a public relay adds seconds), and that mirrors carry a marks.json snapshot to stay verifiable and can go live off the same ephemeral channel.
1 parent 9f6bd16 commit a8d9e55

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

forge/AGENT.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,43 @@ Key properties:
155155
- **CD fan-out:** many subscribers can watch the same repo and each run their
156156
own `postSync` (deploy to different edges, run different builds).
157157

158+
## Live data on a cheaply-anchored mesh — the two-channel pattern
159+
160+
A frequently-changing app (a tracker, a dashboard, a game board) wants two
161+
things that pull against each other: **mirrors fresh in real-time** and **cheap,
162+
sparse Bitcoin anchoring**. Run them as two channels over the same repo:
163+
164+
- **Ephemeral channel (real-time).** On every change, emit a NIP-01 *ephemeral*
165+
event (kind in 20000–29999) carrying the new value — the forge's `/preview`
166+
endpoint does this (kind 21617), or any signer can. Subscribers (the status
167+
page, and the mirror app itself) render it live. **No commit, no mark, no
168+
cost.** Relays don't store ephemeral events, so add a slow heartbeat re-emit
169+
(~30s) so a freshly-loaded page catches the current value. Source the change
170+
from an *event*, not a poll: subscribe to the app's own push stream (or LDP
171+
notifications) rather than watching the filesystem — `fs.watch` dies with
172+
`EMFILE` on a large directory, and polling is the wrong tool when the server
173+
already emits change events.
174+
- **Super-commit channel (durable + anchored).** A periodic *sync* commits the
175+
accumulated state; with **`sparseMarks`** those commits collapse into one
176+
re-targeted pending mark, so the periodic anchor is a single tx per period.
177+
*The sync becomes the next super-commit.* Frequent commits (fresh git mirrors)
178+
and one cheap mark per period now coexist.
179+
180+
**Latency is the relay you choose, not the design.** Route the ephemeral channel
181+
through a relay **you control and co-locate with the consumers**, not a shared
182+
public relay — a public relay can add unpredictable seconds; a local one is
183+
sub-second. *Measure each hop before tuning anything else* (stream → emit → each
184+
relay → render); the slow link is almost always the public relay, not your code.
185+
Emit fire-and-forget so a slow relay's ACK never blocks the next event.
186+
187+
**Mirrors stay verifiable and can go live too.** Ship a `marks.json` snapshot
188+
*inside the repo* (all public data — txids, addresses, commits) so every mirror
189+
carries its own provable mark state and renders the marked tier straight from
190+
Bitcoin, with no reach back to the origin. A static mirror app becomes real-time
191+
by subscribing to the same ephemeral channel (intercept the current-value fetch,
192+
re-render) — appended at deploy time by the subscriber's `postSync`, so the
193+
origin's own copy stays untouched.
194+
158195
## Known walls / upstream
159196

160197
- **Core `--git` shadows plugin-owned git paths.** A server that also runs core

0 commit comments

Comments
 (0)