ADR 0023: Hand-offs as records; event triggers from the audit stream
- Status
- Accepted
- Date
- Deciders
- Founder
Context
Twins of different personas must pass work to each other (an entry ready for an SOP check, a supply slip that blocks a study) without an agent-to-agent channel, and twins must start work when something happens without polling every table.
Decision
handoff_requestsare createdsentonly when the sending person approves the proposal (program.handoffs.manage); statusessent,accepted,declined,done,withdrawn; acceptance opens a program-visible thread pinned to the linked record and fires the receiving twin (twin_handoff); duplicates refused (409handoff_exists), self-addressing refused, routes scoped by party.- Event triggers match a closed
TRIGGERABLE_ACTIONStuple (connector_object.update,hypothesis.decision,sop_version.update,milestone.update,handoff.accept,experiment.update,approval.create) inside a post-flush hook ofwrite_auditthat runs in a savepoint (a hook failure never fails the record write), coalesces per trigger and interval, honours backpressure, and enqueuestwin_cycleruns withon_conflict_do_nothing; anAUDIT_ACTIONSregistry pins every action name;PAUSE_ACTIONS(role_assignment.delete,user.deactivate) pause twins in the same hook; an hourly reconcile job catches anything missed.
Consequences
- Mentions never start a twin; the mentioned person clicks “Let my twin look at this”.
- The hook is structural: no notification, run, interrupt, twin, inbox or sync action can trigger anything (catalogue-style test).
Alternatives considered
- Message bus between agents: invisible to the record; rejected.
- Polling tables for changes: cost and latency; rejected in favour of the audit hook plus reconcile.
Follow-ups
- Cross-program hand-offs (R5).
Last updated on