Repository navigation
RFC 0001 wave 1: senses (0.9.0) - #33
Merged
Merged
Conversation
Every shipped persona and example (tutor, ops-engineer, trader-assistant, the agent-harness retry policies, the monitor's drives demo persona) and two engine test fixtures x seeds 0-2 x four committed random scripts of 100 events (9,600 live turns and as many replayed), plus init, check, describe, compile, lint --seeds 0-99, and lint/fuzz/prove documents of the shipped rules: 653 outputs, recorded with probbit 0.8.2 before any 0.9.0 change. The scripts carry the keys 0.9.0 adds (senses, await, for, cancel) as undeclared inputs, which a persona without the new blocks must keep listing in ignored. fixtures/MANIFEST records the binary's sha256 and every frozen file's; p0.py check compares the binary under test.
An optional senses block (docs/persona.md 2.11): readings the host measures in declared units with
a named source, each judged against a learned normal per sense (mean, variance, count; half-life in
events; drift and variance caps anchored to a declared prior) and moving moods and traits by its
capped, dead-zoned z. Read strictly (every lint row of RFC A.1 at its path), lowered to reserved
sense_<id>_up/down number inputs and sense_<id>_c<N> condition flags; the sense step runs before the
drive step; state senses {genes, norm} checked on read (S4); stance senses and noticed; why gains the
normal clause and, with line.why_past and a learning block, the learned clause (learned_from in the
state). Refusals S1-S3, S5-S6 in the turn; props, fuzz alphabet, forcing and prove read the lowering.
A persona without the block gives every document byte for byte as before (the P0 corpus).
…out the block
verify's summary gains normals {mean, n, max_move_50} for a persona with senses; the strand logs the
readings as given; live warns once on stderr when senses reaches a persona without the block (an
undeclared input, listed in ignored). Tests: P3s (40 individuals x 300 random events mixing sources,
readings, self, clock and out-of-range readings: each run equals its run without the refused events,
byte for byte), normals recomputed by verify, a life split over two runs is one strand.
fuzz adds readings to its events (flags both ways, numbers on the grid x range and at the raw conditions' thresholds), and patterns per reading (repeated 1, 5 and 20 times; range ends alternating); --fixture-src labels readings too. probbit_persona_turn and probbit_live_event refuse an event that carries readings for a persona with a senses block; the schemas declare senses.
A persona without a senses block that receives a `senses` key gets one stderr line from `live` (an undeclared input, listed in ignored as before). The P0 scripts that send the new keys (k=1) get it at their first `senses` event; documents, states and strands stay byte-identical. The check accepts exactly that line, once, where the script carries `senses`, and counts those outputs apart.
examples/persona/sensed.yaml: four senses (tool failures, tool latency, message tempo, silence), two habits on raw readings, learning on caution. The golden drives it through 24 turns with readings; sensed-props.json holds the two habit rules (held by construction for seeds 0-99).
…their first run The sensed persona (and a copy with every sense gene spread at 0), the seeded generator lives.py and its streams (rooms A and B, the month-away tail, 20 probes, habituation and surprise), and the gated bars, each with its sha256 in fixtures/MANIFEST. MANIFEST's p0.py line follows the check's report of the senses warning line (its own commit, logged in the README).
…efuses readings tests/live.rs: readings logged as used and verify recomputing the normals (max_move_50), a sensed life split across runs equal to one run, the one stderr line for readings sent to a persona without the block, P3s (40 individuals x 300 random events: the run equals the run without its refused events, byte for byte), probbit check on a sensed persona. tests/persona.rs: the sensed golden byte for byte. python/test_mcp.py: S7 through both turn tools.
…med inputs Per declared sense: its normal as a tick over the range, this event's reading, z and n; an alert when a normal moved over drift_cap / 2 within 50 events (terminal board and page). The panel of the event's inputs was labelled SENSES; it is now INPUTS, so it does not collide with the senses block (the two pinned frames change by that label only).
twins.py (a: 40 individuals x rooms A and B, 20 probes each), habituation.py (b: the engine against an independent implementation of the sense step, surprise, genes, and the named past rendered from each document), replay.py (d: third and split copies byte for byte, live verify, the P0 strand), habits.py (e: every stance against the habits). run.py checks fixtures/MANIFEST first and exits 0 only when every gated bar passes.
…, BENCHMARKS §10, the bench README persona.md: §2.11 Senses (schema, refusals, the sense step, rules S1-S7, the stance and why), and senses in §3 step 2, §4, §5.1, §5.6, §5.7 and §7; §5.8 names the inputs panel and adds the senses rows; §6 adds the limit. The RFC is docs/rfcs/0001-senses-and-reward.md. BENCHMARKS §10 and the bench README record the measured bars, metric a's failure included.
…ile; docs wording
* bench/individuality: p0 passes repository-relative paths; EXPECTED re-recorded with 0.8.2 A fuzz document that finds a counterexample names the persona path as given in its explain and replay strings, so fuzz/adaptive-fixture depended on the clone's location. Every command already runs at the repository root; personas and rules are now passed relative to it. Re-recorded with the same released 0.8.2 binary: one line changed (fuzz/adaptive-fixture, 43,646 bytes). Logged in the bench README. * persona: learning.credit read strictly; await/for/cancel read and echoed; the credit step and B-R1..B-R6 (WIP) * live: control lines close open decisions, verify summary open, verify --actions; mcp refuses cancel; the one stderr line for credit keys without the block; p0 check accepts it (WIP) * bench/individuality: MANIFEST p0.py line and the README log for the credit-keys stderr line * fuzz: payments resolved against each state (late, reordered, previous, closed, unknown, mismatch; cancels), refused ones change nothing, exported scripts concrete; monitor: open decisions with eligibility, the payment and closures (WIP) * examples/agent-harness: the addressed-outcome variant (addressed.json, late.py, its test) and its cross-OS golden * fuzz: re-running a shrunk counterexample with its payments resolved is not a searched turn, and a persona without a credit block keeps its script as found * persona, live: tests for action-addressed feedback: eligibility at ages 0/3/10/32/127, expiry at 128, eviction, every refusal row B-R1..B-R6 (and byte for byte in live), absorbed, the strict credit state, e = 1 equals 0.8 on every shipped learning persona, control lines, P3c 40 x 300 with a model of the bookkeeping, probbit check on a credit persona * docs: action-addressed feedback (persona.md §2.8 credit, §4 stance credit, §5.1 state, §5.6 payments in fuzz, §5.7 control lines and credit in live, §5.8 monitor, §7), CHEATSHEET, CHANGELOG, the RFC copy (question 2 decided, B-R6), man page for live verify --actions * bench/individuality: metric c frozen before its first run (dispatch.yaml with a credit block and its no-block twin, the seeded draws and their generator, bars-c.json; the plain-inputs control persona for metric a); credit.py and run.py run it * bench/individuality: credit.py runs its 50 host-driven runs side by side, re-runs only the runs that refused events, and reports evictions, expiries and payment ages per run (logged in the README) * bench/individuality: twins_addressed.py re-measures metric a with Design B on the frozen fixture and bars, with the plain-inputs control; BENCHMARKS.md §11 (metric c and the re-measured twins) * examples/agent-harness: README section for the addressed variant; docs, bench and comments: plainer wording (law check) * bench/individuality: README intro: this release runs metric c; metric a's frozen streams and twins_addressed.py * bench/individuality: record the frozen metric a result on this release --------- Co-authored-by: BitmapAsset <bitmapasset@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft: RFC 0001 Design A (senses) for 0.9.0. Not ready for review or merge yet; metric a of the benchmark does not pass its bar (below).
What the block does
An optional
sensesblock (docs/persona.md §2.11, design notes in docs/rfcs/0001-senses-and-reward.md). The host sends measured readings (a tool failure, a latency, a message tempo, a silence) in declared units with a named source. Per sense the engine keeps a normal (mean, variance, count; a half-life in events; the mean held withinprior.mean ± drift_cap, the variance within[0, var_cap]) and turns each reading into a capped z-score against it, which moves moods and traits like a number input. The stance gainssensesandnoticed;whynames the normal a reading was judged against and, with learning, what the learned weights came from (learned_fromin the state).inputs.senses.<id>orinputs.src, and a refused event changes nothing; habits readsense.<id>.rawor.z, never the normal; normals move only on readings; a state whose normals leave their caps is refused; the MCP turn tools refuse events that carry readings.provereads the lowered inputs as boxes, so a habit onsense.<id>.rawholds by construction;fuzzadds readings.live verifyaddsnormals(mean, n, max_move_50);monitordraws a row per sense and an alert when a normal moved overdrift_cap / 2within 50 events; its panel of the event's inputs is now labelled INPUTS.Personas without the block
bench/individuality/p0.py check: 653 outputs recorded with the released 0.8.2 binary before any code change (8 personas × seeds 0-2 × 4 random scripts: 9,600 live turns and as many replayed; describe, lint, fuzz and prove documents): 0 differ. 629 are byte-identical; 24 are the stderr ofliveruns whose scripts send asenseskey, wherelivenow names the undeclared key once; they equal the record once that line is removed. All 8 recorded strands verify, and the tutor's continues with the recorded bytes.Tests and checks (local, Apple M4)
cargo test --workspace --locked(stable): 348 passed, 1 ignored; one timing test in probbit-decide failed under a load average of 16.7 and passes alone (this branch does not touch that crate). Rust 1.78: release build and test build OK. wasm32 build andplayground/check.mjsOK.probbit checkon a sensed persona), one test per refusal row and per rule, MCP refusal in python/test_mcp.py, a monitor test.persona prove|fuzz --depth 16|lint examples/persona/sensed.yaml --props examples/persona/sensed-props.json --seeds 0-99: exit 0 (fuzz: 480,817 turns, nothing found).Benchmark (
python3 bench/individuality/run.py --only a,b,d,e, 10 s; fixtures and bars frozen before any run)In this release rewards pay the previous stance; at these settings a different individual moves the host action more than a different life does. The bars stay as frozen.
Not in this PR
Action-addressed feedback (
learning.credit,await,for,cancel; benchmark metric c), signed rewards and the lineage budget (metric f), and a version bump.