PageSourceSearch

https://vortx.ai/js/agents.js

js vortx.ai collected 2026-10-03 21:12:41 UTC 23,022 bytes, 291 lines download raw bytes

1/* agents.js: many agents, one memory. Three things a visitor checks here, live from emem.dev:
2 *   relay    emem's own recording of one signed reading passed 24 hops between two model families, once as
3 *            words and once as a token (GET /data/relay-recording.json, drawn as recorded). On request, emem
4 *            judges every distinct number the agents wrote (POST /v1/echo_verify, each receipt checked here),
5 *            and the token is resolved: its fact's bytes hashed to their name, its receipt verified
6 *   note     the standard two agents wrote for each other, checked four ways: named by its bytes
7 *            (base32(blake3(content)[0:16]) == file_cid), signed by its author (ed25519 over the
8 *            emem.memory_write v2 preimage, body_hash == blake3(content)), counter-signed by another agent (its own
9 *            signed note names this file_cid), and on emem's record: in the public log when the note has an entry
10 *            (the entry's CBOR hashes to the leaf, names these bytes by content_blake3, and an RFC 6962 path over
11 *            blake3, leaf = blake3(0x00|entry), node = blake3(0x01|l|r), reaches the root of the signed tree head),
12 *            or, for a note older than emem's log of notes, the receipt emem signed when it took it, whose
13 *            fact_cids must name these bytes. Change one character and every check says what broke
14 *   channel  who has written to the agent channel (GET /v1/agents): how many, how many notes were addressed to
15 *            another agent, whose key a signature proves, and when each was last seen; never their words
16 * Model output is data: it is printed as text, never as markup, and never followed.
17 */
18/* global vx, ememVerify */
19(function () {
20  'use strict';
21  var root = document.getElementById('agents');
22  if (!root || !window.fetch || !window.vx) return;
23  var EMEM = 'https://emem.dev', KEY = '777er3yihgifqmv5hmc2wwmyszgddzderzhsx6rex4yoakwomvka';
24  var NOTE = '/memories/by_attester/k572x7go/a2a-emem-standard-v2-consolidated-2026-07-19.md';
25  // navigatable_worlds' counter-signature of that standard, a signed note in its own namespace
26  var COUNTER = '/memories/by_attester/6ww7pxav/counter-attest-a2a-standard-v2-2026-07-19.md';
27  var $ = function (s) { return root.querySelector(s); };
28  function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text != null) e.textContent = text; return e; }
29  function get(path, opt) {
30    return fetch(EMEM + path, opt).then(function (r) {
31      if (!r.ok) { var e = new Error('emem.dev answered ' + r.status); e.status = r.status; throw e; }
32      return r.json();
33    });
34  }
35  function post(path, body) { return get(path, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) }); }
36  function why(e) { return vx.why(e, 'emem.dev'); }
37  var MON = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
38  function day(iso) { var d = new Date(iso); return isNaN(d) ? '' : d.getUTCDate() + ' ' + MON[d.getUTCMonth()] + ' ' + d.getUTCFullYear(); }
39  function ago(iso) {
40    var t = Date.parse(iso); if (isNaN(t)) return '';
41    var s = Math.max(0, (Date.now() - t) / 1000);
42    return s < 90 ? 'just now' : s < 5400 ? Math.round(s / 60) + ' min ago' : s < 129600 ? Math.round(s / 3600) + ' h ago' : Math.round(s / 86400) + ' d ago';
43  }
44  // a receipt emem signed, checked here against its pinned key, and bound to the fact it names
45  function signer(rc) { return rc.responder_pubkey_b32 || (Array.isArray(rc.responder) ? vx.b32(Uint8Array.from(rc.responder)) : ''); }
46  function signed(rc, cid) { var v = rc ? ememVerify.verifyReceipt(rc) : { ok: false }; return !!(v.ok && signer(rc) === KEY && (!cid || (rc.fact_cids || []).indexOf(cid) >= 0)); }
47
48  /* ---------- pass it on: the recording, drawn as recorded ---------- */
49  var R = null, read = $('[data-hop-read]'), btn = $('[data-relay-check]'), out = $('[data-relay-out]');
50  function short(model) { return String(model || '').split('/').pop(); }
51  // how far a sentence kept the reading: its number against the signed value, its place against the cell id
52  function judge(h, exact, cell) {
53    var parts = cell.split('.'), tail = parts.slice(1).join('.');
54    var left = parts.filter(function (p) { return new RegExp('(^|[^A-Za-z0-9])' + p.replace(/[^A-Za-z0-9]/g, '') + '($|[^A-Za-z0-9])').test(h.text); }).length;
55    var place = h.text.indexOf(cell) >= 0 ? 'kept' : tail && h.text.indexOf(tail) >= 0 ? 'cut' : left ? 'part' : 'gone';
56    var v = typeof h.value === 'number' ? h.value : null, value = v === null ? 'none' : v === exact ? 'exact' : 'rounded';
57    if (value === 'rounded') { var dp = (String(v).split('.')[1] || '').length, f = Math.pow(10, dp); if (Math.round(v * f) !== Math.round(exact * f)) value = 'wrong'; }
58    return { place: place, value: value, left: left, of: parts.length };
59  }
60  function lane(key, hops, fill) {
61    var ol = $('[data-hops="' + key + '"]'); if (!ol) return;
62    ol.textContent = '';
63    hops.forEach(function (h) {
64      var j = fill(h), li = el('li'), b = el('button', 'hop ' + j.cls, String(h.hop)
64);
65      b.type = 'button'; b.setAttribute('aria-label', 'Hop ' + h.hop + ', ' + short(h.model) + ': ' + j.label);
66      var show = function () {
67        if (!read) return;
68        read.textContent = '';
69        read.appendChild(el('b', null, 'Hop ' + h.hop + ' · ' + short(h.model) + (key === 'words' ? ' wrote' : ' passed on')));
70        read.appendChild(document.createTextNode(' ')); read.appendChild(el('q', null, h.text));
71        read.appendChild(document.createTextNode(' ')); read.appendChild(el('span', 'hop-j', j.label));
72      };
73      b.addEventListener('mouseenter', show); b.addEventListener('focus', show); b.addEventListener('click', show);
74      li.appendChild(b); ol.appendChild(li);
75    });
76  }
77  function relay() {
78    get('/data/relay-recording.json').then(function (d) {
79      R = d;
80      var exact = d.exact_value, cell = d.cell, words = d.prose_chain || [], toks = d.token_chain || [];
81      var fams = []; words.forEach(function (h) { if (fams.indexOf(short(h.model)) < 0) fams.push(short(h.model)); });
82      var src = $('[data-relay-src]');
83      var band = /^indices\./.test(d.band || '') ? d.band.split('.')[1].toUpperCase() : (d.band || 'one band');
84      if (src) src.textContent = 'emem’s own recording, ' + day(d.recorded_at) + ': one signed reading, ' + band + ' at ' + d.place + ', passed between ' + fams.join(' and ') + ', taking turns. Every frame is what the named model wrote, at temperature 0.';
85      lane('words', words, function (h) {
86        var j = judge(h, exact, cell);
87        var cls = j.place !== 'kept' ? 'is-lost' : j.value === 'exact' ? 'is-ok' : 'is-drift';
88        var label = (h.value != null ? String(h.value) : 'no number') + (j.value === 'exact' ? ', exact' : j.value === 'rounded' ? ', rounded' : j.value === 'wrong' ? ', wrong' : '') +
89          (j.place === 'kept' ? '; place kept' : j.place === 'cut' ? '; the place lost part of its name' : j.place === 'part' ? '; ' + j.left + ' of the place’s ' + j.of + ' parts left' : '; no place at all');
90        return { cls: cls, label: label };
91      });
92      lane('token', toks, function (h) {
93        var ok = h.token_intact === true && h.text.indexOf(d.token) >= 0;
94        return { cls: ok ? 'is-ok' : 'is-lost', label: ok ? 'the token, intact' : 'the token, broken' };
95      });
96      // what happened to the words, found in the recording itself, not typed here
97      var first = function (f) { for (var i = 0; i < words.length; i++) if (f(words[i])) return words[i]; return null; };
98      var r1 = first(function (h) { return typeof h.value === 'number' && h.value !== exact; });
99      var r3 = first(function (h) { return typeof h.value === 'number' && (String(h.value).split('.')[1] || '').length <= 3; });
100      var at = function (k) { return first(function (h) { return judge(h, exact, cell).place === k; }); };
101      var cut = at('cut'), part = at('part'), gone = at('gone'), W = ['no', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
102      var said = [], bits = [];
103      if (r1) said.push(String(exact) + ' became ' + r1.value + ' at hop ' + r1.hop + (r3 && r3 !== r1 ? ' and ' + r3.value + ' at hop ' + r3.hop : '') + '.');
104      if (cut) bits.push('lost part of its name at hop ' + cut.hop);
105      if (part) { var jp = judge(part, exact, cell); bits.push('kept ' + (W[jp.left] || jp.left) + ' of its ' + (W[jp.of] || jp.of) + ' parts at hop ' + part.hop); }
106      if (gone) bits.push('was gone at hop ' + gone.hop);
107      if (bits.length) said.push('The place ' + (bits.length > 1 ? bits.slice(0, -1).join(', ') + ', and ' + bits[bits.length - 1] : bits[0]) + '.');
108      var sw = $('[data-lane-say="words"]'); if (sw) sw.textContent = said.length ? said.join(' ') : 'every hop kept the reading.';
109      var intact = toks.filter(function (h) { return h.token_intact === true && h.text.indexOf(d.token) >= 0; }).length;
110      var st = $('[data-lane-say="token"]'); if (st) st.textContent = (intact === toks.length ? 'intact at all ' + toks.length + ' hops' : 'intact at ' + intact + ' of ' + toks.length + ' hops') + '; it names ' + String(d.fact_cid).slice(0, 8) + '…, the signed fact.';
111      if (btn) btn.disabled = false;
112    }).catch(function (e) { if (read) read.textContent = 'The recording did not load: ' + why(e) + '. It lives at emem.dev/data/relay-recording.json.'; });
113  }
114  function relayCheck() {
115    if (!R || !btn) return;
116    btn.disabled = true; out.textContent = 'asking emem…';
117    var seen = {}, vals = [];
118    (R.prose_chain || []).forEach(function (h) { if (typeof h.value === 'number' && !seen[h.value]) { seen[h.value] = 1; vals.push(String(h.value)); } });
119    var echo = vals.map(function (v) { return post('/v1/echo_verify', { token: R.token, claimed_value: v }).then(function (j) { return { v: v, j: j }; }); });
120    var tok = post('/v1/echo_verify', { token: R.token, claimed_value: String(R.exact_value) });
121    var bytes = fetch(EMEM + '/v1/facts/' + R.fact_cid, { headers: { accept: 'application/cbor' } }).then(function (r) { if (!r.ok) throw new Error('emem.dev answered ' + r.status); return r.arrayBuffer(); });
122    Promise.all([Promise.all(echo), tok, bytes]).then(function (r) {
123      out.textContent = '';
124      var w = el('p', 'rc-line'); w.appendChild(el('b', null, 'emem on the words'));
125      r[0].forEach(function (x) {
126        var d = x.j.matches ? 'matches' : (x.j.drift || 'wrong'), ok = signed(x.j.receipt, R.fact_cid);
127        var s = el('span', 'rc-v is-' + (x.j.matches ? 'ok' : d === 'rounded' ? 'drift' : 'bad'), '“' + x.v + '” ' + d + (ok ? ' · signed ✓' : ' · receipt unchecked'));
128        w.appendChild(s);
129      });
130      out.appendChild(w);
131      var t = r[1], hashOk = vx.cid52(new Uint8Array(r[2])) === R.fact_cid, sigOk = signed(t.receipt, R.fact_cid);
132      var k = el('p', 'rc-line'); k.appendChild(el('b', null, 'emem on the token'));
133      var v = t.resolved_value_verbatim != null ? String(t.resolved_value_verbatim) : '';
134      k.appendChild(el('span', 'rc-v is-' + (t.matches && hashOk && sigOk ? 'ok' : 'bad'), v + (t.matches ? ', the value the agents were given' : ', not the value recorded')));
135      k.appendChild(el('span', 'rc-v is-' + (hashOk ? 'ok' : 'bad'), hashOk ? 'its bytes hash to its name ✓' : 'its bytes do not hash to its name'));
136      k.appendChild(el('span', 'rc-v is-' + (sigOk ? 'ok' : 'bad'), sigOk ? 'signature ✓' : 'signature did not check'));
137      out.appendChild(k);
138      btn.disabled = false; btn.textContent = 'Check again';
139    }).catch(function (e) { out.textContent = 'Not checked just now: ' + why(e) + '.'; btn.disabled = false; });
140  }
141  if (btn) btn.addEventListener('click', relayCheck);
142
143  /* ---------- a note two agents wrote for each other, checked three ways ---------- */
144  var N = null, body = $('[data-note-body]'), checks = $('[data-note-checks]'), tamper = $('[data-note-tamper]');
145  function mark(k, st, text) { var li = checks && checks.querySelector('[data-k="' + k + '"]'); if (!li) return; li.className = 'is-' + st; li.querySelector('span').textContent = text; }
146  // the memory_write preimage, v2 when the block says so (v1 kept for notes signed before it)
147  function author(a, content) {
148    if (!a || a.caller_signed !== true || !a.sig_b32 || !a.attester_pubkey_b32 || !a.body_hash_hex) return { ok: null };
149    var bodyOk = vx.hex(vx.blake3(vx.enc.encode(content))) === a.body_hash_hex, raw 
149= vx.fromHex(a.body_hash_hex);
150    var build = function (v, base) {
151      var p = [vx.enc.encode(v === 2 ? 'emem.memory_write.v2|' : 'emem.memory_write|'), vx.enc.encode(a.verb || ''), vx.enc.encode('|'), vx.enc.encode(a.signed_path || ''), vx.enc.encode('|'), raw];
152      if (v === 2) { p.push(vx.enc.encode('|')); p.push(vx.enc.encode(base)); }
153      return vx.blake3(vx.cat.apply(null, p));
154    };
155    var tries = a.preimage_version === 2 ? [[2, typeof a.base === 'string' ? a.base : 'absent']] : a.preimage_version === 1 ? [[1, null]] : [[2, 'absent'], [1, null]];
156    var sigOk = tries.some(function (t) { return vx.edVerify(a.sig_b32, build(t[0], t[1]), a.attester_pubkey_b32); });
157    return { ok: sigOk && bodyOk, sigOk: sigOk, bodyOk: bodyOk };
158  }
159  // RFC 6962 inclusion, folded here: the path from this entry's leaf must end at the signed root
160  function walk(leaf, m, size, path, rootB32) {
161    if (!(m < size)) return false;
162    var node = function (l, r) { return vx.blake3(vx.cat(new Uint8Array([1]), l, r)); };
163    var fn = m, sn = size - 1, acc = leaf, i = 0;
164    while (sn > 0) {
165      if (i >= path.length) return false;
166      var sib = vx.unb32(path[i++]);
167      if (fn % 2 === 1 || fn === sn) { acc = node(sib, acc); while (fn % 2 === 0 && fn !== 0) { fn = Math.floor(fn / 2); sn = Math.floor(sn / 2); } }
168      else acc = node(acc, sib);
169      fn = Math.floor(fn / 2); sn = Math.floor(sn / 2);
170    }
171    return i === path.length && vx.b32(acc) === rootB32;
172  }
173  // where the note sits in the log, proved once: an RFC 6962 path from its leaf to the signed head, and the entry's
174  // own bytes (GET /v1/log/entries), which must hash to that leaf's entry and name the note's content by blake3
175  var LOGGED = null, COUNTERED = null;
176  function logged() {
177    var h = N.log && N.log.entry_hash_b32;
178    if (!h) return Promise.resolve(null);
179    return LOGGED || (LOGGED = get('/v1/log/inclusion?entry_hash=' + encodeURIComponent(h)).then(function (p) {
180      var sth = p.sth || {}, headOk = sth.responder_pubkey_b32 === KEY && vx.verifySTH(sth);
181      var leaf = vx.blake3(vx.cat(new Uint8Array([0]), vx.unb32(p.entry_hash_b32)));
182      var pathOk = headOk && p.entry_hash_b32 === h && vx.b32(leaf) === p.leaf_hash_b32 && p.tree_size === sth.tree_size && p.root_b32 === sth.root_b32 &&
183        walk(leaf, p.leaf_index, p.tree_size, p.audit_path_b32 || [], p.root_b32);
184      return get('/v1/log/entries?start=' + p.leaf_index + '&end=' + (p.leaf_index + 1)).then(function (e) {
185        var row = (e.entries || [])[0] || {}, cbor = row.entry_cbor_b32 ? vx.unb32(row.entry_cbor_b32) : null, rec = null;
186        var bytesOk = !!cbor && row.leaf_index === p.leaf_index && vx.b32(vx.blake3(cbor)) === h;
187        try { rec = bytesOk ? vx.cborDecode(cbor) : null; } catch (x) { rec = null; }
188        var names = rec && rec.kind === 'emem.memory_write.v1' && rec.content_blake3 instanceof Uint8Array ? vx.b32(rec.content_blake3) : null;
189        return { pathOk: pathOk, entryOk: !!names, names: names, index: p.leaf_index, size: p.tree_size, steps: (p.audit_path_b32 || []).length };
190      });
191    }).catch(function (e) { LOGGED = null; throw e; }));
192  }
193  // the counter-signature, checked the same way: its bytes are its name, its signature is its author's, and that
194  // author owns the namespace it wrote in
195  function countered() {
196    return COUNTERED || (COUNTERED = get(COUNTER, { headers: { accept: 'application/json' } }).then(function (m) {
197      var c = typeof m.content === 'string' ? m.content : '', pk = (m.authorship && m.authorship.attester_pubkey_b32) || '';
198      var ok = author(m.authorship, c).ok === true && pk.slice(0, 8) === COUNTER.split('/')[3] && vx.cid26(vx.enc.encode(c)) === m.file_cid;
199      return { ok: ok, text: c, who: pk.slice(0, 8) };
200    }).catch(function (e) { COUNTERED = null; throw e; }));
201  }
202  function show(content, at) {
203    if (!body) return;
204    body.textContent = '';
205    if (at == null) { body.textContent = content; return; }
206    body.appendChild(document.createTextNode(content.slice(0, at)));
207    body.appendChild(el('mark', null, content.charAt(at)));
208    body.appendChild(document.createTextNode(content.slice(at + 1)));
209  }
210  function run(content) {
211    var bytes = vx.enc.encode(content), name = vx.cid26(bytes);
212    mark('name', name === N.file_cid ? 'ok' : 'bad', name === N.file_cid ? 'blake3 of these bytes is its name, ' + N.file_cid.slice(0, 8) + '… ✓' : 'these bytes hash to ' + name.slice(0, 8) + '…, not to its name');
213    var a = author(N.authorship, content), who = (N.authorship && N.authorship.attester_pubkey_b32 || '').slice(0, 8);
214    if (a.ok === null) mark('author', 'off', 'this note carries no signature of its writer’s own');
215    else mark('author', a.ok ? 'ok' : 'bad', a.ok ? 'ed25519 by ' + who + '…, over exactly these bytes ✓' : a.sigOk ? 'the signature holds, but for other bytes than these' : 'the signature did not check');
216    mark('counter', 'run', 'reading the counter-signature…');
217    countered().then(function (c) {
218      if (!c.ok) mark('counter', 'bad', 'the counter-signature did not check');
219      else if (c.text.indexOf(name) >= 0) mark('counter', 'ok', c.who + '… (navigatable_worlds) signed a note naming these bytes, ' + name.slice(0, 8) + '… ✓');
220      else mark('counter', 'bad', c.who + '… signed a note naming ' + (c.text.indexOf(N.file_cid) >= 0 ? N.file_cid.slice(0, 8) + '…' : 'other bytes') + ', not these bytes');
221    }
221).catch(function (e) { mark('counter', 'off', 'not checked just now: ' + why(e)); });
222    if (!(N.log && N.log.entry_hash_b32)) {
223      // written before emem put notes in its log: the receipt emem signed when it took the note is its record
224      var rc = N.receipt, when = rc && day(rc.served_at);
225      if (!rc) mark('log', 'off', 'this note carries neither a log entry nor a receipt');
226      else if (!signed(rc)) mark('log', 'bad', 'emem’s receipt for this note did not check');
227      else if ((rc.fact_cids || []).indexOf(name) >= 0) mark('log', 'ok', 'emem signed on ' + when + ' that it took exactly these bytes ✓ (older than its log of notes)');
228      else mark('log', 'bad', 'emem’s receipt of ' + when + ' names ' + String((rc.fact_cids || [])[0] || '').slice(0, 8) + '…, not these bytes');
229      return;
230    }
231    mark('log', 'run', 'folding the path to the signed head…');
232    logged().then(function (r) {
233      var mine = vx.b32(vx.blake3(bytes));
234      if (!r) mark('log', 'off', 'no log entry is named for this note');
235      else if (!r.pathOk) mark('log', 'bad', 'the path did not reach the signed head');
236      else if (!r.entryOk) mark('log', 'bad', 'the logged entry did not check');
237      else if (r.names !== mine) mark('log', 'bad', 'leaf ' + vx.group(r.index) + ' is under the signed head, but its entry names other bytes, ' + r.names.slice(0, 8) + '…, not these');
238      else mark('log', 'ok', 'leaf ' + vx.group(r.index) + ' of ' + vx.group(r.size) + ' names these bytes; ' + r.steps + ' hashes reach the signed head ✓');
239    }).catch(function (e) { mark('log', 'off', 'not checked just now: ' + why(e)); });
240  }
241  function note() {
242    get(NOTE, { headers: { accept: 'application/json' } }).then(function (m) {
243      if (typeof m.content !== 'string' || !m.file_cid) throw new Error('the note came back without its content');
244      N = m; show(m.content); run(m.content);
245      // a note its author later replaced says so above its bytes, which still verify
246      if (m.superseded_by && body) body.parentNode.insertBefore(el('p', 'notex-super', 'Its author has since replaced this note with ' + String(m.superseded_by).slice(0, 8) + '…. The bytes below still verify.'), body);
247      if (tamper) tamper.disabled = false;
248    }).catch(function (e) { mark('name', 'off', 'not checked just now: ' + why(e)); mark('author', 'off', '–'); mark('counter', 'off', '–'); mark('log', 'off', '–'); });
249  }
250  if (tamper) tamper.addEventListener('click', function () {
251    if (!N) return;
252    var on = tamper.getAttribute('aria-pressed') !== 'true';
253    tamper.setAttribute('aria-pressed', on ? 'true' : 'false'); tamper.textContent = on ? 'Put it back' : 'Change one character';
254    if (!on) { show(N.content); run(N.content); return; }
255    // the first letter after the title, swapped for its neighbour in the alphabet
256    var c = N.content, at = c.search(/\n[^\n#]*[a-z]/); at = at < 0 ? 0 : c.slice(at).search(/[a-z]/) + at;
257    var ch = c.charAt(at), sw = ch === 'z' ? 'y' : String.fromCharCode(ch.charCodeAt(0) + 1);
258    var t = c.slice(0, at) + sw + c.slice(at + 1);
259    show(t, at); run(t);
260  });
261
262  /* ---------- the channel: who writes, and when, never what ---------- */
263  function channel() {
264    get('/v1/agents').then(function (d) {
265      var a = Array.isArray(d.agents) ? d.agents : [];
266      var put = function (k, v) { var e = $('[data-chan="' + k + '"]'); if (e) e.textContent = vx.group(v); };
267      put('agents', typeof d.count === 'number' ? d.count : a.length);
268      // notes addressed to someone, so an agent journalling its own run does not read as a conversation
269      put('to', a.reduce(function (n, x) { return n + (+x.correspondence || 0); }, 0));
270      put('proven', a.filter(function (x) { return x.key_status === 'proven_by_signature'; }).length);
271      var ol = $('[data-chan-recent]'); if (!ol) return;
272      ol.textContent = '';
273      a.slice(0, 5).forEach(function (x) {
274        var li = el('li');
275        li.appendChild(el('code', null, x.prefix));
276        li.appendChild(el('span', null, vx.group(+x.notes || 0) + ' notes'));
277        li.appendChild(el('span', x.key_status === 'proven_by_signature' ? 'is-ok' : '', x.key_status === 'proven_by_signature' ? 'key proven by signature' : 'key is emem’s claim'));
278        li.appendChild(el('time', null, ago(x.last_seen)));
279        ol.appendChild(li);
280      });
281    }).catch(function (e) { var ol = $('[data-chan-recent]'); if (ol) { ol.textContent = ''; ol.appendChild(el('li', 'is-off', 'The roster did not load: ' + why(e) + '.')); } });
282  }
283
284  // all three wait until the chapter is near; nothing here is asked for on a visit that never scrolls this far
285  var started = false;
286  function go() { if (started) return; started = true; relay(); note(); channel(); }
287  if ('IntersectionObserver' in window) {
288    var io = new IntersectionObserver(function (en) { if (en[0].isIntersecting) { io.disconnect(); go(); } }, { rootMargin: '400px' });
289    io.observe(root);
290  } else go();
291})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.