Skip to content

probbit monitor: watch an individual's inner state live - #21

Merged
BitmapAsset merged 13 commits into
mainfrom
r61-monitor
Oct 7, 2026
Merged

BitmapAsset merged 13 commits into
mainfrom
r61-monitor

Conversation

@BitmapAsset

@BitmapAsset BitmapAsset commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

probbit monitor: watch an individual's inner state live, inside the probbit binary, with no dependencies: as bars in the
terminal, or as a page in the browser served from 127.0.0.1.

It replays a strand (the header holds the persona, the initial state and the engine version; one line per event holds the
inputs) with the rules of probbit live verify, recomputing every stance document from the strand alone, so it works for any
strand on any machine and needs no extra log. It says "replay verified" when the chain checks, and names the line when one
differs. It changes no file (the demo's week goes through a temporary one, removed at once) and sends nothing anywhere.

probbit monitor --demo --open: the tutor's week in the browser

Done against the done-when list below, CI green on ubuntu, macOS, Windows and wasm at the head; a draft until it is reviewed.

  • A. Subcommand: probbit monitor STRAND [--follow] [--once] [--plain] [--fps N] [--serve] [--open] [--port N] and
    probbit monitor --demo [--once] [--plain] [--serve] [--open] [--port N] (--open serves the page as --serve does and
    starts the browser), with help in the style of the other subcommands
    and exit codes 0 (every line replays), 1 (a line differs: named in the frame, which shows the event before it), 2 (a bad
    flag, a port that cannot be had, an unreadable file, a file that is not a strand). Terminal view: one row per trait (its
    levels as segments with their odds, the level taken highlighted, its phrase), moods with a sparkline of the last 50 events,
    senses (flags, levels, numbers, the clock, history features), habits (bound ones marked, the violations counter), learned
    deltas as centred bars within the cap, drives rows when a document carries pursue / drives (feature-detected), the stance
    line and why. --plain is plain ASCII; colour follows the existing theme rules (NO_COLOR, PROBBIT_THEME=plain,
    TERM=dumb).
  • B. Replay engine shared with live verify: done. live::Replay (open the header, step one line, summary); verify is a
    loop over it, and the existing live tests pass unchanged. Unit tests replay strands of the three example personas (each
    one's scripted --demo week, seed 2, and a strand that lights every input in turn) and check each monitor document's sha256
    against the line's stance digest, on every line, and that the replay ends where verify does. --follow draws an
    appended line within a second (tested), replays a truncated strand from the start with a warning, waits out a removed one
    and follows a rotated one (tested).
  • C. Server: done. --serve binds 127.0.0.1 with std TcpListener and no other address (there is no host flag; --host
    / --bind exit 2 saying so), port 0 by default (a free one) or --port N; the URL is the line on stdout. It answers GET
    requests addressed to 127.0.0.1:PORT or localhost:PORT (others get 403, so a page of another site that resolves its name
    to 127.0.0.1 cannot read the documents): / the page (one file embedded in the binary, 21 KB, styles and script inline,
    a Content-Security-Policy that lets it connect to nothing but its own server), /events server-sent events (the layout,
    the latest frame, then a frame per event; a heartbeat comment after 15 quiet seconds; events that land within one 100 ms
    poll, or while a page falls behind, come as the latest frame), /doc/N event N's stance document as
    probbit live printed it (the latest 10,000 kept). The strand is followed with the same replay as --follow; while a
    long strand replays from its header (10,000 events: about 3.5 s), the page and the terminal draw the board every 250 ms
    with a note. --open starts the default browser (BROWSER, else open / cmd /c start / xdg-open), best effort: a
    browser that does not start fails nothing. A thread per connection, at most 64 at once. Nothing beyond std, so the same code
    on macOS, Linux and Windows; the server tests run in the existing CI matrix.
  • D. Demo mode: --demo in the terminal (paced at a terminal; --demo --plain --once deterministic and tested) and
    probbit monitor --demo --open (or --serve without the browser), the week paced 1 s per hour and each night in 2 s,
    over and over, for the page (a week that starts over goes from its last event straight to event 1; the night's note sits
    in the header row, so the board holds still).
  • E. Tests: tests/monitor.rs: help; a --once --plain frame pinned byte for byte on the tutor's demo week (the last
    event and a failure turn); exit codes; --follow pickup, truncation, removal, rotation; and the server: GET / (the page,
    under 40 KB, no URL in it but the SVG namespace), /doc/1..3 equal to probbit live's stdout lines byte for byte, 404s,
    the host guard (403), /events (the layout, then the latest frame with that document; a line appended to the strand is
    pushed as the next frame and /doc/4 serves it), a port in use (exit 2), --open with a browser that does not start
    (the server runs on), --demo --open serving the demo's page and stream, and the flag errors (7 tests). Unit tests (9):
    replay equals verify on the three personas' scripted weeks and on strands that light every input, plus any strands named
    in PROBBIT_MONITOR_STRANDS (a copy of a real 14-event strand passes); a hand-written document with drives / pursue
    draws its rows, and passes through to the page's frames as it is (the page draws it too, checked in headless Chrome: no
    script error); a long replay is published on the way; the event stream's heartbeat (a 100 ms beat in the test); the page's
    layout follows the persona's order; the embedded tutor equals the example; cell rounding.
  • F. Docs and assets: CHANGELOG lines under 0.8.0 (unreleased); docs/persona.md §5.8 (the board, the terminal flags, the
    --serve routes and frame fields, the host guard, the demo, exit codes) and its row in the command table; README "Watch it
    live" right after "Live" (three lines, probbit monitor --demo --open, the GIF) and the documentation map; the cheat
    sheet's monitor rows and exit codes; docs/agents.md (a person can watch the individual behind a strand_path).
    docs/probbit-monitor.gif: the tutor's week in the browser, 1280x720, 14.9 s, 1,895,852 bytes (headless Chrome screenshots
    of --demo --serve every 400 ms, assembled with ffmpeg at 10 frames/s, a 128-colour palette); docs/probbit-monitor.png:
    the page at event 21, a failure turn (no_jokes_on_loss bound, humour none 1.00).
  • G. Gates: cargo test --release --workspace green locally (macOS arm64, 54a1794: every suite, probbit-decide's
    acceptance 19/19; that crate is unchanged, and its wall-clock asserts need its CI threshold on a machine at load 50+);
    clippy: 0 new warnings; no new dependencies (Cargo.lock unchanged); release binary 2,317,328 bytes vs 2,190,320 on main,
    +127,008 bytes (macOS arm64). CI at 54a1794: green on every job (tests on ubuntu, macOS and Windows, wasm, the four
    release targets).

main.rs changes are one module, one match arm and one usage line.

…he terminal

live::Replay checks a strand's header and replays it line by line with the rules
`live verify` used (prev, n, the stance and state digests, the bytes); verify is now
a loop over it, so the monitor and verify read a strand one way.

`probbit monitor STRAND [--follow] [--once] [--plain] [--fps N]` replays the strand,
recomputing every stance document, and draws the latest event as horizontal bars:
the stance (each trait's levels as segments with their odds, the level taken
highlighted, its phrase), the moods with a sparkline of the last 50 events, the
senses, the habits (bound ones marked, violations), the learned deltas within
their cap, drives when a document carries them, and the stance line. A line that
differs is named in the header and the frame shows the event before it (exit 1).
--follow polls the file and replays appended lines; a truncated or rotated strand
is replayed from the start with a warning. --plain is ASCII only.
tests/monitor.rs: help; one --once --plain frame pinned byte for byte (the tutor's
demo week, the last event and a failure turn with a bound habit); exit 0 / 1 (a
changed input: the frame names the line verify names and shows the event before
it) / 2; --follow draws an appended line within a second, replays a truncated
strand from the start, waits out a removed one and follows a rotated one. A frame
at a terminal keeps the rows that fit. Prose kept to the repo's word list.
…(unset in CI)

The replay-equals-verify check as a helper: every document's sha256 is its line's stance digest and the replay ends where verify does. The three example personas run it always; strands named in the environment (paths joined as in PATH) run it on demand.
`probbit monitor --demo [--once] [--plain]` plays the week `live --demo week` writes
(the tutor, seed 2): live::week writes it to a temporary strand, read back and
removed, and the monitor replays it, at a terminal paced 1 s per hour and each
night in 2 s; piped, or with --once, its last frame. The last frame equals the
pinned frame of the fixture week but for the footer (tested); the embedded tutor
is examples/persona/tutor.yaml (tested). Follow mode and the demo share one
in-place redraw that keeps the rows a terminal fits.
…stream, /doc/N

A std TcpListener bound to 127.0.0.1 (no other address; requests addressed to another host
are refused) serves one page embedded in the binary (monitor.html, 21 KB, styles and script
inline), its server-sent events (the layout, the latest frame, a frame per event, a heartbeat
every 15 s) and /doc/N, event N's stance document as probbit live printed it. The strand is
followed with the replay --follow uses; --demo --serve plays the week over and over. --open
starts the default browser, best effort. Tests: the page, the documents byte for byte, the
stream (a line appended is pushed), the host guard, a port in use, the flag errors.
… 127.0.0.1, the demo

What the board shows, --once / --follow / --plain, --serve's routes (/, /events and its frame
fields, /doc/N), the loopback bind and the host guard, the demo week, the exit codes; the
command table and the intro point to it.
A failed assert in the --serve test left its server running (the child outlived the test
process). The children of the --follow and --serve tests are now killed on drop, passing or not.
…d, a still of the page

README: a section after Live: probbit monitor in three lines, the demo command and docs/probbit-monitor.gif (the tutor's week in
the browser, 1280x720, 14.9 s, 2.5 MB), and the documentation map. CHEATSHEET: the monitor rows and exit codes. agents.md: a
person can watch the individual behind a strand_path. docs/probbit-monitor.png: the page at event 21, a failure turn
(no_jokes_on_loss bound).
… week starts over without an empty board

The note (a quiet night, a truncated or rotated strand) sat on its own line under the header and pushed the board down while it
showed; it is now part of the header row (on a narrow page it wraps there). When the demo week started over, the page drew the
empty board for a moment before event 1; the week now goes from its last event straight to event 1. docs/probbit-monitor.gif
captured again (1280x720, 14.9 s, 1.9 MB).
…y file removed at once)

The help, the module notes, the CHANGELOG and docs/persona.md §5.8 said the monitor writes nothing; with --demo the week
goes through a temporary strand (written by live::week, read back, removed). They now say it changes no file and name the
temporary one. The CHANGELOG lines are wrapped again.
A strand read from its header is replayed before the board shows its last event: 10,000 events take about 3.5 s, and the
page said 'waiting for the strand' meanwhile (the terminal stayed blank). The replay now draws the board every 250 ms on the
way, with the note 'replaying the strand from its header: the board catches up': --serve publishes those frames (and the
documents so far), --follow redraws at a terminal. Unit test: a replay published at every event (6 frames for 5 events, the
last without the note) and at none on the way (1 frame). Checked by hand on a 10,000-event strand: 14 frames with the note
over the page's event stream, then event 10000; 16 redraws at a pty. docs/persona.md §5.8: one sentence.
… in the browser

- `--open` alone serves the page as `--serve --open` does: `probbit monitor --demo --open` plays the tutor's
  week in the browser (it exited 2 with "--open goes with --serve"). Help, usage line, README command, cheat
  sheet, docs/persona.md §5.8 and the CHANGELOG say so; a CLI test serves the demo with --open.
- /events heartbeat tested: a 100 ms beat in a unit test (15 s when served), before the strand has replayed
  and after a frame.
- Each example persona's scripted week (seed 2) replays to its digests (unit test).
- §5.8: events that land within one 100 ms poll, or while a page falls behind, come as the latest frame.
CHANGELOG: one 0.8.0 section, drives first, then the monitor. README: Live, Drives, Watch it live.
The monitor's learned rows take the levels of `pursue` from the drives block's goals (describe hides
that trait), in the terminal and on the page; a unit test replays a real drives strand to its digests
and checks the drives and learned rows.
@BitmapAsset
BitmapAsset marked this pull request as ready for review October 7, 2026 07:59
@BitmapAsset
BitmapAsset merged commit 34c3bdc into main Oct 7, 2026
8 checks passed
@BitmapAsset
BitmapAsset deleted the r61-monitor branch October 7, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant