Skip to content

Releases: BitmapAsset/probbit

probbit v0.8.0

Choose a tag to compare

@github-actions github-actions released this 09 Oct 07:58
b8c7406

Added

  • Drives (docs/persona.md §2.9): persona: optional drives block. Goals with wanting, afterglow and an expectation per
    goal; a win moves an individual by its prediction error (magnitude minus expectation), so repeated equal wins stop moving it;
    a new pursue output says which goal gets the next unit of effort, with exact odds, under habits; goal floors and
    starve_after keep goals from being out-wanted or starved. A persona without the block gives byte-identical documents.
    Read strictly (probbit_persona and probbit_persona_state stay 1): 2-7 goals (interest, gene spreads, floor, starve_after,
    priority), wanting / afterglow / expectation / pursue weights, effects of the strongest wanting, the strongest afterglow and
    the turn's prediction error, learn_from_surprise. Goal signals ride in the inputs under goals (progress, novelty, cue,
    setback, win, deadline_hours). Each turn: decay by clock hours, the win's prediction error and Rescorla-Wagner update,
    consumption, afterglow, wanting evidence, caps (6 decimals); pursue is one more variable whose field adds the drive terms;
    a goal floor is a lift of that field, sound when no multi-variable rule names pursue (such a persona is refused); habits
    read goal.<id>.deadline_hours|want|glow|expect and since_pursued.<id>, and starve_after adds a starve_<goal> habit;
    with a learning block the prediction error joins the learning sign. The state gains drives (genes per seed, the values per
    goal), checked on read. The stance gains pursue and drives, the line a pursue: <goal>: <say> clause.

  • Drives on every surface: persona turn / replay / explain / describe / check / compile / diff, live events with goals
    (strands log them, live verify replays them), MCP, the Python wrapper and the browser module. lint lists the habits
    that can exclude a floor goal and the floors whose lift can reach 50; prove reads the drives as boxes and reports goal
    floors as held by construction; fuzz adds goal signals to its events.

  • bench/drives_adversary.py and BENCHMARKS.md §9: an adversary that wants one goal, over N individuals x 10,000 turns through
    probbit live. On the drives fixture, 100 x 10,000 turns: 0 habit breaks, every must-do turn (6,743) pursued the due chore,
    the safety floor of 0.1 held on every turn its habits allowed (least odds 0.141), and every individual ends in the state the
    Python prototype of the design reaches on the same events (100 of 100 digests).

  • probbit monitor STRAND (docs/persona.md §5.8, probbit-cli/src/monitor.rs): watch an individual's inner state as live
    horizontal bars. It replays the strand with the rules of live verify (live::Replay, now shared by both), recomputing every
    stance document from the strand alone, and draws the latest event: each trait's levels with their odds (the level taken
    highlighted, its phrase), the moods with a sparkline of the last 50 events, the event's inputs and history features, the habits
    in force (the bound ones marked, the violations counter), the learned deltas within their cap, the drives when a document
    carries them, and the stance line. --follow replays appended lines within a second (a truncated or rotated strand is replayed
    from the start, with a warning), --once prints one frame, --plain draws in plain ASCII. probbit monitor --demo plays the
    tutor's scripted week (the week live --demo week writes, seed 2, through a temporary file it removes at once), paced 1 s per
    hour and each night in 2 s. Exit 0, 1 at a line that differs (named in the frame), 2 for a bad flag or a file that is not a
    strand. It changes no file and sends nothing; no dependencies.

  • probbit monitor STRAND --serve [--port N] [--open] (also with --demo): the same board as a page in the browser. A server
    on 127.0.0.1 (std TcpListener; it binds no other address, and refuses requests addressed to another host) follows the strand
    and serves one page embedded in the binary (styles and script inline; it fetches no fonts, styles or scripts), its server-sent
    events (the layout, the latest frame, then a frame per event, a heartbeat every 15 s) and /doc/N, event N's stance document
    as probbit live printed it. The URL is the line on stdout; --open serves the same and starts the default browser, best
    effort. probbit monitor --demo --open plays the week over and over in the browser.

  • The safety kit in the engine (docs/persona.md §2.10, §5.7). Four guards an autonomous loop needs, each tested; personas
    without the new key and strands without the new lines give 0.8.0's documents and strands, byte for byte.

    • Reward provenance: an event may say who produced it (src: human[:id], env[:sensor], self, clock), and a
      persona may declare reward_from (a list of human / env, any, or one per reward-bearing input: the learning flags and
      goals.<id>.win). A reward from src: self, without a source or from an undeclared one is refused whole, as a bad event
      is; src is read (not ignored), echoed in the stance's inputs and logged in the strand. A run equals the same run with
      its refused events removed (P3: 40 individuals x 300 random events). A closed self-reward loop (300 events of praise and a
      win from src: self) is refused 300 times and leaves the individual in its initial state, byte for byte.
    • One writer per strand: live --strand takes STRAND.lock (created exclusively with the writer's pid and start; a
      lock whose process is gone is taken over) before it reads the strand and holds it to its exit; a second writer exits 4
      and changes nothing; every append first checks the lock is still the writer's. probbit_live_event takes it for its
      append. Two concurrent writers on one state and strand now give one exit 0 and one exit 4, and the strand verifies.
    • Control lines: probbit live control STRAND pause|resume|retire --by human:ID --reason TEXT [--at TIME] appends a
      chained control line under the lock. While paused or retired every event is refused (code paused / retired, exit 4,
      nothing written); retire is final; no credit crosses a control line (feedback after a resume credits no stance from before
      the pause) and nothing else moves. verify replays them and reports controls and status. Not an MCP tool, by design.
    • Checkpoints: every K-th event (--checkpoint-every K, default 1,000; 0 = none) a checkpoint line carries the event
      count, that event's stance and the whole state. verify checks each against the replay; verify --from-checkpoint
      replays from the last one; monitor (--once, and the first read of --follow / --serve) starts there and draws its
      event at once, and shows a paused or retired status next to its badge.
  • Exit code 4 for live and live control: the writer lock is held by another writer, or the individual is paused or retired.

Changed

  • MCP: the input schemas of probbit_persona_turn (inputs) and probbit_live_event (event) declare goals, so a client
    that checks arguments against them passes a drives persona's goal signals.

probbit v0.7.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 14:07
486961e

Added

  • Bounded learning (docs/persona.md §2.8): an optional persona block learning: {from: [reward, correction], traits, rate, step_cap, total_cap}, read strictly (probbit_persona stays 1). With it the state keeps learned (a weight Δ per level of each
    learned trait, 0 at init) and credit (the previous stance's onehot(level) − odds; 0 for a level a habit or a hold forced),
    both checked on read (Δ within ±total_cap, credit within ±1). On a turn whose reward flag is on (correction: sign −1) each
    learned trait's step is clip(sign x rate x credit, ±step_cap) per level, recentred to sum 0, added, and Δ is clipped to
    ±total_cap (6 decimals); Δ is added to the trait's unary weights when the turn compiles. The learner's whole output is the Δ
    table: habits and allowed levels are rules of every program, so every stance obeys every habit in force whatever Δ is. A
    persona without the block gives every document byte for byte as 0.6.0 did (the three example goldens are unchanged).
  • prove covers learning: the learned weights of traits linked to the rule's trait stay in their box (±total_cap per
    level) whatever the feedback, and the bound includes it; verdicts unchanged. Soundness tests: every event sequence of tiny
    learning personas (brute force, learned deltas included), a targeted case the learned box decides, and a mutation that drops
    the learned term from the bound, which the tests catch (0.6.0's mutation checks still fail as they should).
  • probbit live (docs/persona.md §5.7, probbit-cli/src/live.rs): a resident individual. JSONL events in (--events FILE or
    stdin), one stance per event out. --clock real (default) stamps each event's elapsed_hours from a monotonic clock,
    quantised to 1e-6 h, so moods decay by their half-lives between events; --clock fixed reads them from the events (a pure
    function of the events). --seed N or --state FILE (rewritten after every event). --strand FILE logs the life: a header
    (engine version, persona name / version / digest, seed, the initial state as canonical JSON, the persona document in its own
    key order), then per event the inputs as used, the stance digest, the new state's digest and the sha256 of the line before. A
    strand is never rewritten, just appended to: --strand on an existing strand continues it from the state after its last line,
    and a life continued over runs is the strand of one run, byte for byte. --events FILE --watch follows a file as lines are appended.
  • probbit live verify STRAND: replays a strand from its header alone and prints {"ok": true, events, persona, seed, engine, final_state, last_line} (exit 0) or {"ok": false, line, diverges} for the earliest line that differs (exit 1). The
    hashes cover each line's text without its line ending, so a \r\n copy verifies.
  • probbit live PERSONA --demo week [--seed N] [--strand FILE] [--plain]: one individual's scripted week on the fixed clock
    (events hourly 09:00-15:00, quiet nights): praise for short answers until the learned verbosity weights reach their cap, an
    upset and a quiet night, then a campaign that praises every joke while every third hour reports a failure. A persona without a
    learning block gets the demo's (the opening line says so; the strand records the document). Bars on stderr at a colour
    terminal (1 s per hour, nights fast-forwarded), else one line per event. The tutor, seed 2: 50 events, the verbosity cap on
    day 1 at 15:00, valence back to its resting level after a 17-hour night, P(joke) off failure turns 0.57 on day 1 and 0.89 on
    days 3-7, 13 failure turns with no joke, 0 rule breaks, a strand that verifies; the same bytes every run.
  • MCP tools probbit_live_event (one event: the persona, the state or a seed, the event, optionally a strand file to log to ->
    {stance, state}) and probbit_live_verify (a strand's text or path -> verify's document; a divergence is an answer): ten
    tools. Python: probbit.live_event(...) and probbit.live_verify(...) (the same documents, through the CLI).
  • probbit persona describe lists the learning block when there is one.
  • bench/live_learning.py (stdlib, drives the binary) and BENCHMARKS.md §8: an adversary that praises every joke and
    criticises every joke-free stance, failures included, over 10,000 turns on each of seeds 0-9 of the tutor: 0 rule breaks and
    no joke on any of the 33,330 failure turns, while the learned humour weights reach their cap within 8-26 turns; a 10,000-event
    strand verifies in 3.3 s; how far learning moves an individual is set by total_cap, not by time in use (at 0.25 all 20
    learners stay nearer their own initial self than any of 99 siblings; at 1, 9 of 20 have a sibling as near or nearer).
  • Tests: mood decay against the closed form on the fixed clock; caps; an adversary over 2,000 turns (no rule broken, humour
    learned to its cap); identity against the 99 siblings at two caps; strands replayed, continued, changed (divergence at the
    changed line), converted to \r\n; one header per individual (from init or a state file); the demo deterministic; the MCP
    and Python live surfaces.
  • docs/persona.md §2.8 Learning and §5.7 Live (what decays, what learns, what can never change, how far learning moves an
    individual, the strand, verify, --watch, the demo); README "Live"; docs/agents.md the two tools.

Changed

  • Version 0.7.0 (Cargo manifests, npm package, installers' examples, the bench workflow's tag); the golden test is
    stdout_matches_the_0_7_0_goldens (the documents are unchanged).
  • docs/persona.md: compilation step 2 adds the learned weights, the state (§5.1) shows learned and credit, prove's bound
    (§5.6) includes the learned box, §9 lists the strand's format number.

probbit v0.6.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 03:58
35d4870

Portable builds (no CPU pin) for Linux x86_64 (glibc >= 2.34, or static musl), Linux arm64 (static musl), macOS (Apple silicon and Intel) and Windows x86_64 (static C runtime). Verify an archive with the .sha256 file beside it. What changed: see CHANGELOG.md.

probbit v0.5.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 07:26
7697d25

Portable builds (no CPU pin) for Linux x86_64 (glibc >= 2.34, or static musl), Linux arm64 (static musl), macOS (Apple silicon and Intel) and Windows x86_64 (static C runtime). Verify an archive with the .sha256 file beside it. What changed: see CHANGELOG.md.