orrery · the console and its fleet · 29 October 2026

A room of machines, and a row of verbs

orrery is the console the operator stands in front of: a computer lab to select from, buttons that open a shell or take control of a machine, a pane that writes the SD cards the fleet is made of, and a queue that trains a game's brain on every machine in the room. The lab reports say what was built and how it was proved; the design set below is what the build followed.

32 lab reports, 93 check-ins 9 machines, 12 lanes 3 CUDA cards 12 phases, all done 370 tests

What was built, and how it was proved

Lab reports

Each in the same form: an abstract, the objective, the materials, what was done, the results with their numbers, and a discussion that keeps what is still open. Every page is built from its Markdown by tools/report/build.py.

6 Nov 2026Crucible · round the corner

Round the Corner: What a Net Needs to Pass a Maze, the Senses That Were Not Enough, the Errand That Was, a Proving Ground, and the Breach

What a net needs to pass a maze, from the robotics and neuroevolution literature: a route sense, its own future along three arcs, two memory cells, progress paid along the route. Senses alone passed no maze in three arms; the rules' errand, the game's own routing under the net, passed every route. The proving ground, the breach.

6 Nov 2026Fleet · what a generation keeps

Outgrowing Yourself: What the GPU Hands the Game, What a Generation Keeps, and Whether the Card-Hours Pay

How a GPU result reaches main (a net file, two roads, nothing shipped by either yet; no GPU number in the line's dials), what the cards cost ($1.41 a day) and bought, why the world ladder stopped at a net that never loses, a generation's turnaround (1 h to commit, 4.6 h to main), and how much of its claim it keeps: 0.28.

6 Nov 2026Crucible · one rule, two machines

One Rule, Two Machines: Trees, Mazes and Takeovers on the Card, a Gauntlet Both Can Read, and Generations the GPU Can Earn

The card's arena gets the game's forest, walls and takeover and its score; the CUDA gauntlet plays treadcore's gauntlet files on the card, fifteen of them with mazes shaped S, 5 and @, paired; training plays them as tasks; a GPU generation is elected on the weighed gauntlet against a bar that follows the line's projection; the terms explained.

6 Nov 2026Crucible · every generation on film

Every Generation on Film: the Maze Home on the Fleet, One Wall in Two Games, a Camp of Rewards, a Full Card, and a Machine That Reads the Page

The maze home on the fleet; one wall rule in two games (game 9); 256 duels a net to fill the card; every new generation's tests filmed and reeled; a camp of stages whose rewards fall with time; which census maps tell a verdict soonest; a card beside every net; and a page that scrolls itself and becomes a small video.

6 Nov 2026treadcore · brain

The brain: lab report and design

The game's brain, a section a step: 154 sections so far. The newest: 154. A wall takes the gun: two direct hits open a gap, as crucible's walls do; the breach by the gun in range; game 9, 6 November

3 Nov 2026Brain

The Nets Explorer

Every learned net the fleet made or keeps, one scrolling window: where each .bin has been, what read it, its weights as a fingerprint, its notes; the lineage from parent to child. A vault that copies only on request, promotes to milestone, and expires only when asked.

30 Oct 2026Brain

Reading a Growing Game Brain

A fitness terrain from past reads, a spectrogram of weights across champions, singular values of each matrix and their product, the senses as the tank has them, and the fleet's road. No peak above today in six dial pairs, which is weak evidence; norm growth is not shown to be skill.

30 Oct 2026Brain

Many Versions of One Brain

What the A/B found, and whole-number choices of rewritten functions. The enum is sound; no switch could ever have been promoted, for two faults, both mended; pings off at +1.99 a seat is the first. A design for several functions doing one job, new senses read only by the chosen one, A/B/C/D.

30 Oct 2026Fleet

Commanding the Fleet

How the buttons were made to work, layer by layer: 77 checks of the listener, 25 of orrery's own client against it and 25 of the tool, on stock Alpine and Ubuntu; a rule broken and restored; and the Fleet screen, with the CA, each machine and what each button can do. Pictures from the real machines, and Fleet Chat as one room hosted by orrery.

30 Oct 2026Fleet

Fleet Commanders

From Timbuktu's buttons to a listener, and selecting machines by what they are. sshd, a certificate and a forced command on Ubuntu and Alpine, 38 checks on each, a login that reads the fleet's last message; a selector by system, idle, version, package and the treadcore commit. Control and Snapshot are still open.

29 Oct 2026Storage

Shared Storage for the Fleet

What the disks are, the one way through, and the NVMe for a small Ceph. A survey of 45 disks and 20 Ceph candidates; NFS 4.2 between the Linux machines, SMB for the Mac, Ceph on three 10 Gb nodes; the Storage view's patch bay; and a 10 Gb card on jaguaribe, unplugged.

29 Oct 2026Machines

Two Copal Machines Join the Fleet

Keys, setup, errands and updates by themselves. The key reached the new machines through saskatchewan, a Copal setup recipe fixed the Machines view's dead ends, and every machine now updates daily and at boot. Along the way: the queue knew how to power off only one machine.

29 Oct 2026The search

A Difficulty for Promotions

How often the brain should change, measured. A bar that lowers itself, like a block's difficulty; why one promotion every 20 minutes would make the brain worse; the floor; and main red since a promotion committed one file of two.

29 Oct 2026CUDA

One Source for Two CUDAs

crucible on Pascal (CUDA 12.9) and Ada (CUDA 13) from one source with no DEFINE, the card naming its own architecture, and the CUDA 13 build proved in Docker on an ARM Mac with no NVIDIA card.

Longer pages

Guides and write-ups

What the build followed (27 October)

The design set

Written before a line of the console was, in ~/code/orrery/docs/ and ~/code/copal-alpine-linux/docs/. Every phase of the plan is now done; the sections below are the argument as it was made, kept as written.

docs/user-guide.html 671 The user guide (28 October 2026). The fleet as one computer, with treadcore as the first template: every view and button of the Training and Sessions views, a real forward pass of the learned tank, the clustering design, and convergence at today's run rate. Start here.
docs/appkit-gui-lab-report.md 1237 From Cargo to a Mac application (28 October 2026): a Rust program with an AppKit window and no crates, taught a layer at a time with a working example, docs/appkit-example/ (orbit), every file in its appendix. The autorelease pool, Retina, events, the bundle, the launcher, the signature.
docs/mac-app-lab-report.md 227 Orrery and copal-tm as Mac applications (28 October 2026): the bundles, their launchers and icons, ad-hoc signing, and what Gatekeeper makes of it. tools/mac-app.sh makes Orrery.app; the same report is in copal-tm.
docs/fleet-train.md 242 The fleet queue's manual: its folder, its files, its commands, sync, shutdown, and what happens when a machine goes away.
docs/console.md 257 The museum interface. The object model, the screen, the verbs, and what it refuses to offer.
docs/surface.md 306 One canvas, two platforms. The Surface seam, Wayland input, the AppKit backend, the baked keymap, the widgets.
docs/wire.md 378 The credential rule, rewritten. crypto.rs, SSH, SFTP, TLS 1.3, RDP — and the one place “no dependencies” genuinely breaks.
docs/media.md 204 Cards, images and machines. The front end to copal-prep.sh, the card ledger, and the manifest.
docs/plan.md 301 The schedule. Twelve phases, what proves each one, the risks ranked, and what would make the plan wrong.
copal-alpine-linux/docs/fleet-control.md 356 The node’s half. What copal-prep.sh grows, and the one thing that turns out to need no change at all.

Read first

Three things in the repositories changed the design

None of these were assumptions. Each came out of reading what copal-prep.sh and copal-fleet.sh already do.

Already built

Terminal needs no change to a node

orrery’s README says a shell needs “a second credential with a wider door than the operator certificate has.” It has one. copal-prep.sh:28383 writes fleet-human into /etc/ssh/principals/$PI_USER, and copal fleet login has always signed -n fleet-operator,fleet-human.

One certificate, two principals, two doors: the forced command on one account, an ordinary login shell on the other. Stage 16 built it and the README recorded it as a gap.

Resolved

The session word settles GUI versus Control

The README records it unresolved: x11vnc cannot capture Wayland, --gui cannot run on X. They are not alternatives — /etc/copal/session selects the remote server and the console reads the word.

x11 nodes get Observe and Control over RFB, which src/rfb.rs already speaks. wayland nodes get them over RDP. On a Wayland node the console and Control now want the same session type.

The real limit

H.264 is where “no dependencies” breaks

Not SSH and not TLS — those are large, but every line has a published test vector. A video codec has no small correct subset, and libavcodec is a dependency on the one machine that cannot fetch one.

So EGFX is not negotiated. Plain bitmap updates with RLE instead — the same choice rfb.rs made asking for Raw and CopyRect only.

docs/console.md

The museum interface

Four regions, each a rectangle draw.rs already knows how to fill. There is no window manager inside the window: no floating panels, nothing overlapping. A pane that opens — a terminal, a screen, a result column — replaces the lab, so there is never a question of what is on top.

orrery --guimuseum · 8 nodesoperator
 ┌──────────────────────────────────────────────────────────────────────────┐
 │ orrery   museum                     ● live      8 declared · 7 up · 6 bus│
 ├────────────┬─────────────────────────────────────────────────────────────┤
 │ SCENES     │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │
 │  show    5 │  │museum-01 │ │museum-02 │ │museum-03 │ │museum-04 │        │
 │  wake    1 │  │● up  44° │ │● up  45° │ │● up  51° │ │● up  46° │        │
 │  rest    1 │  │show      │ │show      │ │sdr-source│ │show      │        │
 │            │  └──────────┘ └──────────┘ └──────────┘ └──────────┘        │
 │ TAGS       │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │
 │  wall    2 │  │museum-05 │ │museum-06 │ │museum-07 │ │museum-08 │        │
 │  sdr     1 │  │● up  47° │ │warden    │ │○ missing │ │◐ silent  │        │
 │  north   3 │  │show      │ │wake  39° │ │08:12     │ │rest  48° │        │
 │            │  └──────────┘ └──────────┘ └──────────┘ └──────────┘        │
 │ STRANGERS  │                                                             │
 │  epson-XY10│  ── seen, never contacted ───────────────────────────────── │
 ├────────────┴─────────────────────────────────────────────────────────────┤
 │ Observe  Control  Terminal  Exchange │ Send  Message  Run  Scene  Power   │
 ├──────────────────────────────────────────────────────────────────────────┤
 │ 3 selected · museum-01 museum-03 museum-05          operator · cert 7h12m │
 └──────────────────────────────────────────────────────────────────────────┘
Strangers are a row, not tiles. A machine on the LAN that is not in this fleet has no selection box, so no verb can ever be aimed at one. The refusal is structural rather than a check.

The arity of the selection is a first-class thing

Half the verbs mean something different on one node than on eight, and two of them mean nothing at all on eight. So the verb bar is redrawn every time the selection changes, and a verb that cannot apply is absent rather than greyed — the same rule the web console already follows for the write route in the gallery posture, for the same reason.

In the gallery posture the dispatch table is empty

On the web, the distinction is a route that does not exist. In a native window there is no route, so the equivalent commitment is that a keystroke which would have been a verb finds nothing to call. A gallery screen is a machine an unattended member of the public is standing in front of, and “the button is hidden” is not a security property.

Timbuktu’s verbs, by name

What a button does

Every row is either a command a person could have typed or a session aimed at one node. There is no third kind.

VerbOne nodeA selectionWhat it runs
Observeview-only screenthe wall is observe-manyRDP or RFB, input never sent
Controlscreen, keyboard, pointerrefusedRDP on Wayland, RFB on X11
Terminala shellrefusedSSH as the login user, fleet-human
Exchangetwo-pane file browserrefusedSFTP over the same connection
Sendpush a filepush to allSFTP put, per-node result
Messagebannerbanner on allneeds a node verb — §4
Runone verbfan-out, a result eachcopal fleet run --node ID
Scene—applycopal fleet scene … apply NAME
Snapshotrestorerestore eachrun … snapshot restore
Poweroff / rebootthe end of the dayon is the supply’s job, not ssh
Notifywhen this is upwhen all eight are upcopal fleet notify --all-up
Media——the cards, images and VMs pane

Refused on purpose

Control on a multi-selection is a design decision, not a missing feature. Broadcasting keystrokes to eight machines produces divergent state nobody can see, and the operation actually wanted is Scene or Run — both declarative, both reporting per node. §IV-C of the lab report is emphatic and verbs.rs already encodes it. The button is simply not drawn when the selection is larger than one.

docs/wire.md

The credential rule, rewritten

The console’s architectural test was that it opens no socket, holds no credential, knows no subject names. A shell needs a key. SFTP needs a key. RDP needs a TLS session. So the rule is restated rather than quietly dropped.

The new invariant

orrery uses the operator credential it was pointed at. It never creates one, never stores one, never prompts for one, never forwards one, and never outlives one.

Six clauses, each of which is a check somewhere in the code. There is no keygen — a missing operator key is an absent button and a sentence, not an offer to make one. There is no password field anywhere in the program. The certificate’s eight hours are the session’s ceiling, counted down in the status line.

Four modules, and why they are one job

SSH and TLS want the same arithmetic. Write crypto.rs once and the second protocol is a wire format rather than a cryptosystem.

  src/crypto.rs   the primitives           ~2000 lines, every line has a test vector
       │
       ├── src/ssh.rs    SSH-2 transport + auth + channels   ~1400
       │        └── src/sftp.rs   SFTP v3                    ~600
       │
       └── src/tls.rs    TLS 1.3 client, one suite           ~1100
                └── src/rdp.rs    RDP client                 ~2200
SHA-2, HMAC, X25519, Ed25519, ChaCha20-Poly1305 and AES-GCM are wanted by both branches. This is the least risky part of the plan, not the most — every function has a published answer in RFC 7748, RFC 8032, RFC 8439, FIPS 180-4 or the NIST GCM known-answer tests.

Host verification is the fleet’s, and it is better than ssh’s

ssh on the Mac checks a node against known_hosts — trust on first use, a file that accumulates, and a warning everybody learns to ignore when a node is reimaged. orrery has the fleet’s CA at ~/.copal/ca/<fleet>_ca.pub, and sign_one() installed a host certificate on every enrolled node. A reimaged node connects; a machine that is not this fleet’s fails at the signature. There is no first-use prompt, because there is nothing to decide.

The H.264 arithmetic, stated rather than hoped

A 1280×720 frame, 24-bit, uncompressed
2.6 MB
At 6 fps, full-screen changes
126 Mbit/s
A Zero 2’s link
100 Mbit/s
Interleaved RLE on a typical desktop
5–15×
What actually travels: damage rectangles
a few KB/frame

Which is to say: Control over RDP will be good for a desktop and bad for video. Dragging a window will be smooth; playing the exhibit’s video full screen will be a slideshow. The honest description of this feature is “you can drive a node from across the room”, not “you can watch it”.

NLA is refused. Network Level Authentication means CredSSP, which means NTLM, which means MD4, RC4 and a design whose entire purpose is to carry a password to a machine before that machine has proved anything. It is a large amount of code to implement a worse security property than the one already in hand.

docs/plan.md

Twelve phases, ordered so that stopping is survivable

The riskiest work is late because its investigation is cheap and its implementation is expensive. The most useful work is early.

Phase · what it adds · what proves it
#PhaseLinesProved by
0The seams — extract trait Surface150--frame output byte-identical
1Input and the toolkit — wl_seat, ui.rs, the keymap1,600weston headless; synthetic input streams
2The Mac backend — AppKit, no runtime classes800--gui opens on the Mac
3The museum interface — the first phase worth having alone1,100every screen rendered to a committed PPM
4crypto.rs — the primitives2,000published test vectors, Wycheproof
5ssh.rs and Terminal2,000sshd in a container, not only the fake
6sftp.rs, Exchange and Send900OpenSSH’s own sftp-server
7tls.rs — TLS 1.3, one suite1,100openssl s_server -tls1_3
8rdp.rs, Control and Observe2,450hypr-rdp on a node, and nothing else
9The media pane — ledger, sequence checks, manifest600a scratch fleet, written to images
10The copal side — verbs, facts(), the Makefile800make lint
11The truth pass — the corrections—three “Still open” entries stop being true

Three defensible places to stop

After phase 3 there is a native fleet console on a Mac and on a node, with a selection model and per-node results, driving the CLI verbs that already exist — about 2,600 lines. After phase 6 it also has a shell and file transfer. Phases 7 and 8 are the part that can be cut, and they are the only part that depends on anything unverified.

The size of it, before agreeing to it

TodayAddedAfter
orrery, lines of Rust7,224~11,400~18,600
of which protocol and crypto903~7,300~8,200
binary, release, stripped471 KB—~1.4 MB
resident, serving1.1 MB—+1 framebuffer

Two to three times the program that exists, and most of the new weight is the wire. The interface itself is about 2,600 lines and is the part that makes the console usable; everything after it makes a button work that is otherwise absent.

Ranked, and named rather than glossed

What can go wrong

IDRiskIf it lands
R1 hypr-rdp will not send bitmap updates to a client with no H.264 decoder Control over RDP does not happen. wayvnc + rfb.rs instead — the code is written and tested. Phase 8 finds out before 2,200 lines, not after.
R2 hypr-rdp cannot be obtained or built at all Same fallback, found in the first hour of phase 8.
R3 Hand-written crypto has a subtle flaw Mitigated by test vectors and by narrowness — one algorithm per slot, verify-only where possible. Not eliminated. The argument is the LAN and the certificate posture, not “it is correct”.
R6 11,400 lines is a lot of program to hold The phase boundaries are the mitigation: 0–3 is a console, 4–6 is a console with a shell, 7–8 can be cut.
R4 objc_msgSend ABI mistakes in mac.rs ~25 distinct call signatures, no runtime class creation. Crashes loudly rather than silently.
R5 The baked US keymap is wrong for the operator Known and stated. A real limitation, not a bug — the alternative is libxkbcommon, a dependency, on the machine that cannot fetch one.
R7 The binary triples and a Zero 2 has 512 MB 1.4 MB resident against 22 MB for the Python prototype is still the argument. Measure on saskatchewan at phases 3, 6 and 9 rather than at the end.

The assumption under R1 and R2

hypr-rdp is not in either checkout, is not in Alpine’s package index as far as these repositories know, and nothing here has run one. Every claim in the design about what it will accept is written against the description it was given. Phase 8 therefore begins by obtaining it, running it on a node, and reading what it actually negotiates with a known-good client — not by writing a client against a guess.

And what would make the whole plan wrong

If a shell on a node turns out to be unwanted — if the real workflow is copal fleet run and never a prompt — phases 5 and 6 are 2,400 lines serving a button nobody presses. The way to test that is phase 3: use the console for a week with only the CLI verbs, and see what is missed.

If the Mac is not where the operator stands, phase 2 is 800 lines of AppKit for nothing. It is in the plan because answers.txt, the CA, the token ledger and the card reader are all there — but that is an inference from the repository, not something anyone said.

copal-alpine-linux/docs/fleet-control.md

The node’s half

Two new verbs in the forced command, and one refused

copal-fleet-exec is, in its own words, the security boundary, and a verb this file does not know is a refusal and a line in the log, not an attempt.

remote start | stop | status is the only genuinely new authority in the design — it lets a certificate holder put a machine’s screen on the network — so it is bounded four ways, all on the node: it reads /etc/copal/session and decides for itself which server to start; it binds to the LAN address only; it stops itself after COPAL_FLEET_REMOTE_MINUTES, default 30; and it logs both ends. This answers the README’s “Nothing on a node can start x11vnc.”

message TEXT is the banner the lab report wants and verbs.rs currently refuses to offer. 200 characters, a charset allow-list rather than a deny-list, and exec with the text as one argument — never a shell string.

send is refused and will not be added. Send is SFTP as the login user over the fleet-human door. A file-transfer verb in the forced command would mean the service account growing the ability to write arbitrary paths, which is the boundary the file exists to hold. Two doors, two jobs — collapsing them would make the forced command decorative.

What does not change

  • fleet_sshd_policy() — the Match block, the forced command, PermitTTY no, AllowTcpForwarding no. All of it stays exactly as written.
  • The principal files and cmd_login() — already correct, and the reason Terminal costs nothing on the node.
  • The CA’s handling — orrery reads the public half to verify host certificates and never touches the private half. A program holding both would be a program worth stealing.
  • The bus — nothing here publishes, subscribes, or knows a subject name.
  • The card-writing path — copal-prep.sh picks the disk and asks for both typed ERASE confirmations. The pane is a front end to that, not a replacement for it.

The acceptance test is the morning, not a build

§V of the lab report, driven from the window instead of the terminal: eight tiles at 08:31, one missing. Click the north tag, Power on. Notify all-up chimes at 08:34. Terminal into museum-03, no password asked. Send an exhibit asset to the wall tag — two nodes, two results. Control museum-06, which is Wayland. Scene show on all eight: seven results and one refusal, drawn as seven and one rather than as a failure. Write card 8, the only unused token in the ledger, and watch the manifest gain a row. At 17:00, Power off, and the certificate expires by itself an hour later.

One of those nine steps can fail for a reason nothing here controls. Every other step is built out of things that exist.