Sign in to edit tickets from this page.

← all tickets · home

Adjudication events include entity_transitions

resolved db34b6ab-0ceb-4511-a27d-19c7a3345859

created_at
2026-04-23
updated_at
2026-04-24
code_context
src/kernel.rs, src/persistence.rs, src/minds.rs
priority
P2
ticket_type
feature
parent
8894dd80
resolved_at
2026-04-24
resolution
accepted

Body

CONTEXT

Child of 8894dd80 (model adjustments for the web UI). See that parent ticket for motivation, non-gaps, out-of-scope list, and parallelization map. This ticket is narrowly scoped to Gap 3.

================================================================ THE CHANGE

Today intent_adjudicated audit events carry entities_touched: Vec<String> (semantic entity ids) but don't expose the actual state transition per entity. Reconstructing the state change for a specific entity requires loading the turn payload and diffing against the previous turn's payload.

Add an entity_transitions array to the intent_adjudicated event, populated at adjudication-apply time, shaped:

[ { "entity_id": "crumb", "state_before": "a small bread crumb...", "state_after": "consumed" }, ... ]

One entry per entity listed in the entity_mutations array of the Adjudication. Captured in apply_adjudication BEFORE the state_before is overwritten by the new state.

entities_touched stays exactly as-is — this is additive, not a replacement. The two fields have different purposes:

Both derived from the same entity_mutations list; both cheap.

adjudication_rejected events do NOT get this field. Those events record a draft that was never applied; there was no transition. The rejected draft's entity_mutations (if it had any) are already in the raw_response field.

================================================================ WHERE THE CODE LIVES

src/kernel.rs::apply_adjudication

src/kernel.rs::PendingAuditEvent::Adjudication variant

src/kernel.rs::run_turn (the adjudicate step)

src/kernel.rs::flush_attempt_events

src/persistence.rs::log_adjudication

================================================================ WHAT DOES NOT CHANGE

================================================================ MIGRATION

events.jsonl files written before this change lack entity_transitions on their intent_adjudicated events. Consumers (the view, future analytics) should treat a missing field as "unknown, pre-change event" — NOT assume empty transitions. Emit a deserializer default of Option<Vec<EntityTransition>> if any reader round-trips these events through a typed struct; None means pre-change, Some([]) means an adjudication that legitimately produced zero transitions.

That said: current production registry is recent and turns are cheap to re-seed. The handler does not need to build a migration path. If existing events become unparseable under a stricter deserializer, that's acceptable and matches the "no fallbacks" discipline.

================================================================ TESTING

Seed a world, run a turn that mutates at least one entity, read the resulting intent_adjudicated event from events.jsonl, assert:

The ant scenario's turn 1 (where the ant crawls east) is a natural fixture — one entity touched, transition from "at the center of the plate, feeling hungry." to whatever the model narrates.

If there's a test fixture with multiple touched entities, assert the transition order matches the order of entity_mutations in the adjudication (not sorted — insertion order, matching what the model produced).

================================================================ ACCEPTANCE

================================================================ SCOPE DISCIPLINE

Proposed resolution

Implemented, committed, merged, deployed, and smoke-verified in production.

What changed:

Mid-stream bug fixed: the initial implementation captured state_before from entity.state.clone() immediately before overwrite in the mutation loop — which reports the wrong value for any entity already mutated by agent_state_after or by an earlier mutation for the same id. Caught by the new live-router test failing on a turn where the LLM happened to include the agent in entity_mutations; fix (pre-apply snapshot HashMap) now documented inline in apply_adjudication.

Unchanged per spec:

Receipts:

Deploy + production smoke:

Child of 8894dd80. I am not confirming — over to you.

History (4 events)

Sign in as a human to drive this ticket from the page, or use the MCP tools.