Skip to content

probbit persona: the individuality layer (CLI, MCP, Python, wasm) - #9

Merged
BitmapAsset merged 1 commit into
mainfrom
r31-persona
Oct 3, 2026
Merged

BitmapAsset merged 1 commit into
mainfrom
r31-persona

Conversation

@BitmapAsset

@BitmapAsset BitmapAsset commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

probbit persona gives an agent an individual temperament that lives outside the model. A persona file (YAML subset or JSON:
traits with priors, moods with inertia, couplings, per-turn inputs, history features, habits as hard rules) + an individual's
state + a turn's inputs compile to ONE probbit-ir program, answered in process by probbit run's own instruction at fixed work.
The stance (a level per trait with exact odds, the habits in force and the ones that changed it, a refusal when the engine cannot
vouch, a why, a stance line of at most 40 estimated tokens) and the next state are canonical JSON. Format: docs/persona.md.

What is in it:

  • CLI probbit persona init | turn | replay | explain | diff | lint | check | compile | describe (probbit-cli/src/persona.rs),
    a strict YAML-subset reader (yaml.rs), a strict validator (one {"error": {"code": "persona", ...}} object, exit 2), one
    canonical number rule for every digest (docs/persona.md §5.2), SHA-256 in process. No dependency added.
  • MCP probbit_persona_init, probbit_persona_turn in probbit mcp (stateless; the CLI's documents).
  • Python probbit.persona_init, persona_turn, persona_replay.
  • Browser probbit-wasm ops 4 and 5; the playground's "Meet three individuals from one persona".
  • Docs docs/persona.md, a README section "The individuality layer", rows in docs/agents.md, CHANGELOG.
  • Examples examples/persona/: three fictional personas (YAML + JSON, one digest each) and their goldens.

Parity: the goldens equal an independent reference implementation's documents byte for byte (state0, all 20 workday stances,
the final state, lint), except that each engine.program digest is of a program whose IR key is probbit_ir (the reference ran
the 0.4.0 engine, key pbit_ir; the program texts are otherwise byte-identical on every turn). A further 5,400 random-input turns
(3 personas x 3 seeds x as written / values: semantic / forced onto the sampler; held, yielded, refused and fallback turns)
are equal too.

Tests (all new, probbit-cli/tests/persona.rs and probbit-wasm/tests/persona.rs): stdout_matches_the_persona_goldens (both
file forms, init / compile / 20 x turn / replay / lint), the YAML subset's accepted and refused cases, 1,000-turn replays
byte-identical across processes and against turn --state, habit properties over 2,160 turns of 12 random personas (every habit
in force re-checked, 481 bound habits broken by the habit-free twin, positional == semantic), lint (clean examples, planted
contradictions statically, at load and at run time), the evaluate bridge at judge weight 0 == the run path (625 trait answers),
refusals (no unvouched trait in the line), 600 malformed documents (never a crash, one error object), Python 3.9
(python/test_persona.py), MCP answers == CLI answers (python/test_mcp.py), wasm documents == CLI documents. The CI wasm job's
check.mjs also replays the three personas in the real browser module against the goldens.

Changed in existing files: probbit mcp lists seven tools (the two persona tools after the five; python/test_mcp.py's two
tool-list assertions updated); sys.rs gains loadavg(); usage and help list probbit persona. No other command's behaviour or
output changes; the 0.5.0 golden digests are untouched.

Checks (final sha 20c8529ad613):

  • CI run 37088504110: green on ubuntu, macOS and Windows (test: cli 65, persona 10, evaluate 8, stress 11 + 1 ignored,
    acceptance 19, ir 47, core 4, wasm no_threads 3 + persona 1), the wasm job (check.mjs: each persona's 20 workday stances in the
    real module equal the goldens) and the four release targets.
  • Local (Apple M4, macOS 26.5.2): cargo test --release --workspace 159 existing + 1 ignored + 11 new; the two wall-clock tests of
    probbit-decide/tests/acceptance.rs miss their 10 ms local limit only at 1-minute load 33-46 (they pass on CI).
  • Clippy: no warning in any added file; the edited files' warning set is unchanged.
  • Python 3.9.6: test_persona.py 5, test_mcp.py 8, test_probbit.py unchanged and passing.
  • A turn in process: median 0.20-0.32 ms, p95 0.22-0.67 ms (N = 1,000 per persona, load 3.3-3.5). Binary 1,400,880 -> 1,862,432
    bytes (+461,552); wasm module 839,523 -> 1,169,601 bytes (+330,078).
  • No dependency added (Cargo.lock unchanged).

A persona file (YAML subset or JSON: traits with priors, moods with
inertia, couplings, per-turn inputs, history features, habits as hard
rules) + an individual's state + a turn's inputs compile to ONE
probbit-ir program, run in process by probbit run's own instruction at
fixed work. The stance (levels with exact odds, habits in force and
bound, refusals, a why, a stance line of at most 40 estimated tokens)
and the next state are canonical JSON.

- probbit persona init|turn|replay|explain|diff|lint|check|compile|
  describe (probbit-cli/src/persona.rs); a strict YAML-subset reader
  (yaml.rs); a strict validator (one persona error object, exit 2)
- one canonical number rule for every digest (docs/persona.md 5.2);
  SHA-256 in process, no dependency
- MCP tools probbit_persona_init and probbit_persona_turn (stateless)
- Python probbit.persona_init, persona_turn, persona_replay
- probbit-wasm ops 4 and 5; the playground's "Meet three individuals
  from one persona"
- docs/persona.md, a README section, docs/agents.md rows, CHANGELOG
- examples/persona: three fictional personas (YAML and JSON) and their
  goldens, equal to an independent reference implementation's documents
  byte for byte (its program texts carry the pre-rename IR key)
- tests: goldens byte for byte, the YAML subset's cases, 1,000-turn
  replays, habit properties over 2,160 random-persona turns, lint, the
  evaluate bridge, refusals, 600 malformed documents, Python 3.9, MCP
  answers == CLI answers, wasm documents == CLI documents

python/test_mcp.py: the tool-list assertions now expect the two persona
tools after the five existing ones.
@BitmapAsset
BitmapAsset merged commit 20c8529 into main Oct 3, 2026
8 checks passed
@BitmapAsset
BitmapAsset deleted the r31-persona branch October 3, 2026 02:17
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