Reference · Receipts v1
Every decision the brain makes leaves a receipt. Two record kinds, two files, one rule: fields are added, never renamed or removed. "v" is bumped only for a change that breaks this promise, which is not planned. lw why and lw watch render from this page.
| record | written by | file |
|---|---|---|
| reflex receipt | student_runtime._receipt() — one per character per sweep | ~/lw-mining/decisions/receipts-YYYYMMDD.jsonl |
| flywheel record | coach._log_decision(kind, payload) — one per deliberator event, plan or say | ~/lw-mining/decisions/YYYY-MM-DD.jsonl |
Both are JSON Lines, append-only, one object per line.
Base fields, present on every row:
| field | type | meaning |
|---|---|---|
| v | int | schema version, 1 |
| t | float | unix seconds, 2 dp |
| world | string | the feed's world id (skyrim-riverwood, mock, …) |
| tab | string | the feed's tab (which adapter) |
| npc | int | the character's scan index in this feed frame — reshuffles per tick; address by name |
| name | string | the character's name (lowercased key elsewhere) |
| probs | object | the reflex head: every one of the 16 actions → probability (4 dp), after any manifest mask |
| action | string | the argmax action |
| conf | float | its probability, 4 dp |
| tau | float | the restraint gate this brain runs at (0.85) |
| served | string | who served this tick — see the table below |
The 16 actions: stay watch idle_social greet_approach serve warn_say investigate flee confront call_help claim_task resume_task complain demand guard_player go_station. The first three are calm and emit nothing.
Conditional fields:
| field | type | present when | meaning |
|---|---|---|---|
| features | object | served != "calm" | the 43 named inputs the head saw, 4 dp (dist_n, player_armed, armed_close, unmet_need, has_command, … the full list is student_features.FEATURES, which ships) — calm rows omit it, they dominate volume |
| episode | string | the character is inside an arc | the active intention's id, or cast:<role> under a scene lease |
| mask | object | a manifest masked this head | {pre: {action: p}, post: {action: p}, masked: [verbs]} — the head before and after the mask, and what was masked out |
| desire | string | served is intention / intention-over-order | the plan step that fired (operator name, e.g. report, refuse-service) |
| evidence | string | same | the journal line the intention rests on |
| plan | list | same | the whole composed plan, operator names in order |
| step | int | same | 0-based cursor into plan |
| subject | string | same | who the intention is aimed at (lowercased name), or absent for the player |
| target | string | same | what the step bound to at fire time (guard, ally:<name>, station:<label>, …) |
| target_handle | int | same | the engine handle of that body/object, when known |
| top2 | list | served == "escalated" | [[action, p], [action, p]] — the two the head was torn between |
| tup | string | served == "escalated" | the serialized situation tuple the flywheel trains on |
| why | string | some escalated rows | the escalation reason |
| cmds | list | some rows | the commands this decision sent |
served — the tiers| value | tier | meaning |
|---|---|---|
| emitted | acted | a confident reflex fired |
| calm | quiet | a calm action; nothing sent (the zero-traffic case) |
| held | refusal (LW3002) | confident but the ladder held the body (order, lease) |
| routine | quiet | the day: placed at a station |
| intention | acted | a plan step fired |
| intention-over-order | acted | a plan step fired by breaking an order — always spoken |
| intention-hold | quiet | a standing plan owns the tick, nothing to fire yet |
| escalated | unsure | below tau; the situation went to the flywheel and the verdict lane |
| escalation-held | unsure | same dilemma, already escalated this window (debounce) |
| quiet-dilemma | unsure | torn between calm options; settled locally |
| llm-verdict | acted | a parked verdict served one to two ticks after its dilemma |
| recast | acted | a scene lease re-applied its pose |
Any of the unsure tiers repeating past a threshold for one character with no intention row between them is the LW4001 starvation signature lw watch detects.
{"v": 1, "t": 1789174224.2, "kind": "<kind>", "decision": {...}, "state": {...feed frame...}, "tuple": "..."}
state is the last feed frame the coach saw; tuple is the serialized situation when one could be built. decision is the payload, by kind:
| kind | payload keys | meaning |
|---|---|---|
| deliberator_wake | name cls outcome id plan ms | one per wake() call — the unit the hosted deliberator is planned on. outcome is intention or declined |
| deliberator_decided | name id cls verb manifest_verb step target target_handle xy need | a plan step fired |
| deliberator_step_advance | name id plan from to desire why | the cursor moved (why: fires, ttl, bind-skip, never-blocked) |
| deliberator_plan_done | name id cls plan last_step why | the campaign ended |
| deliberator_bind_skip | name id step skipped subject need verb reason | a step skipped at fire time — nobody to bind to (LW3021) |
| deliberator_never_blocked | name id step skipped verb rule when | a never-rule fired at fire time (LW3010) |
| deliberator_no_admissible_verbs | name arch cls source reason | the manifest left nothing to compose from |
| deliberator_escalation | name cls arch traits wake_text wake_t situation candidates (+ text, recalled, ambient) | a wake no law covered — the ranker lane's raw material |
| deliberator_plan_escalation | same shape | a torn or swapped plan — same lane |
| deliberator_rank | name cls chosen composer because | the ranker's choice vs the composer's |
| deliberator_rank_error | name where err | the ranker failed and the composer decided |
| deliberator_stand_down | name excul grudge law semantic because | forgiveness stood a plan down |
| deliberator_hold_course | name excul grudge because | amends offered, plan held |
| deliberator_amends_nothing_to_forgive | name cls text | amends with nothing live |
| deliberator_swap | name to score | a graver wrong replaced the plan |
| deliberator_wait | name id desire suppressed_say | a wait step |
| deliberator_need_unmet | name need reason | a need with no way to meet it |
student_escalation / student_escalation_verdict | the student's tuple + the LLM verb | the student lane's raw material |
| obedience_broken | name order reason line | an order ended aloud |
| manifest_blocked | name verb where | the funnel backstop caught a disallowed command |
plan / raw / student | the command sent | every command that left the coach |
A receipt contains the character's name, the feed frame (positions, identities), the feature row, and for intention rows the journal line it rests on. The flywheel record contains journal text under wake_text / text / recalled. lw sync --dry-run prints exactly which of these leave the machine, by lane; the gate lane (raw text) is a separate opt-in.