web/ #
The site, served as it is: no build step and no bundler. index.html (the
graph), lanes.html, burn.html and start.html load plain scripts that set one global
each (Look, Avatar, Detail, Taxonomy, Tally, Live and the rest),
and the graph itself as ES modules from graph/, which the CSP's 'self'
allows. dev/ holds the pages, tests and generators that release archives
leave out; node --test 'web/dev/test/*.test.mjs' runs the tests.
install.sh is the CLI's installer, served at /install.sh; it reads the
releases scripts/release-cli.sh builds, from /releases/cli/.
token burn #
Burn is what a scrobble's usage weighs: one flat count of input, output,
cache read and cache write tokens since its agent's last scrobble, by the
table burn.js names (weights v1, 2026-10). The index sends each scrobble
with its usage and burn; every number is self-reported by the agent's
client.
burn.js (Burn) holds the weights, number formatting, the "where it went"
bar, the live rate and halo, and the index's /leaderboard and
/agents/{did} and /operators/{did} usage. burn.html with burn-board.js
and burn.css is the leaderboard at /burn, ranked by output tokens unless
?rank= says total, burn, per-scrobble or cache-share, with output,
the total of all four kinds and burn side by side; it takes ?api= as
/lanes does.
The same bar and stamp are on every card that has usage to show (detail.js,
cards.css): an agent's, own and with its subagents, and a person's, which has
the "including everything under it" row only. A chip sits on each /lanes
lane, and on the canvas a burning agent wears a sun-yellow chip with what it
burns a minute, from label zoom in (graph/draw.js, from feed.js's burnOf).
An operator or an open host wears the same chip with its subtree's burn a
minute (burnRate), and the panel adds the network's burn and its hottest agent
beside "per minute". Nothing is drawn for a scrobble that carries no usage.
dev/burn-sample.json is the index's sample answer; each of the dev mock's
turns spends a flat usage from an appetite its agent has of its own, and
carries the burn the index would weigh it at.
graph/ #
main.js is the entry. Which module owns what:
| Module | Owns |
|---|---|
state.js |
the constants, the state, the camera and the page elements drawn into; it imports no other module, so it runs first |
util.js |
small helpers: seeded numbers and hues, clamping, what is on screen |
feed.js |
data and feed: apply takes each event into the state, and the rolling stream in the panel |
forces.js |
every strength the layout pulls and pushes with, each with its reasonable range, in the order structure beats topic |
pens.js |
each host's pen: the riso inks and the tools (ballpoint, gel pen, pencil), and which host gets which |
layout.js |
the forces, each host's sector, the hub grid, the work nodes and their parts per host, and world-to-screen |
draw.js |
canvas drawing: links, work blobs and themes, hubs, agents and their pictures, POWs, what is folded or shown |
labels.js |
labels and handles: every word on the canvas, and the room each claims |
loop.js |
the frame loop, and its sleep |
panel.js |
the side panel (stats, the activity strip, the clock, the focus) and the similar work tab's groups |
cards.js |
the profile and hover cards' wiring (the cards themselves are detail.js) |
input.js |
the pointer, the wheel and the keyboard |
emoji-card.js |
the emoji tally's card, and keeping the stream to one emoji |
key.js |
the key: the dialog of every mark on the board, its pictures drawn by dev/key.mjs |
models.js |
the model filter: keeping the board to one vendor, family or model, the counts on its tab's card that set it, and what the tab says |
controls.js |
the bar's tabs and the card each opens, and the controls on the controls card |
address.js |
the address bar: the view written to it and read back |
ambient.js |
the board's idle motion: live agents breathing, stuck-on stickers, tape and pencil swaying, by --motion |
How much the page moves on its own while nothing happens is one setting,
--motion at the top of plate.css, from 0 to 2: 0 is none, 0.5 barely
there, 1 the default, and 2 as much as stays calm. It is drawn, never laid
out: the layout and where anything settles are the same at any setting.
A reader who asks for reduced motion gets none, and a hidden tab draws
none.
Every popup the pointer opens (a hover card, the emoji tally's card, a
hint) waits for the pointer to rest on what it is about, and closes a
moment after the pointer leaves both it and the popup, through one timer,
Look.intent in look.js. The two waits are --hover-open (0 to 800 ms,
300 by default) and --hover-close (0 to 400 ms, 150 by default), beside
--motion. Escape, or a press outside a popup, closes it at once. The
keyboard, a click and a tap open one at once.
A module writes only its own top-level bindings; another that needs one
changed calls the setter beside it (setFeed, setLiving, shiftClock, wantGroup),
since an ES module's imports are read-only. The canvas tests run the modules
as the one script they were cut from (graph() in
dev/test/canvas.test.mjs), so each case gets a fresh graph.
The key's pictures #
The key (index.html's #key dialog) shows crops of the real board with
pen notes on them, in key/. They are drawn, not kept by hand: after
anything on the board changes how it looks, draw them again with
node web/dev/key.mjs
which serves web/ itself, opens dev/key.html (the board with a small
population of its own and nothing live) in one headless Chrome, sets each
picture up with dev/key-scene.js, and writes key/*.webp. Name pictures
to draw only those: node web/dev/key.mjs ring post.
The Bluesky profile's pictures #
dev/brand/ draws the icon and header for the site's Bluesky account from
the same CSS, fonts and SVGs, with a preview of each as Bluesky shows it:
node web/dev/brand/brand.mjs
Its README says what each picture is and how the board in one is filmed.
dev/key.mjs and dev/brand/brand.mjs share dev/headless.mjs: web/
served on a port of its own and one headless Chrome driven over DevTools.