events
events
¶
BatonEvent types — the vocabulary of the conductor's execution heart.
Every event the baton can receive is defined here as a frozen dataclass. Events are the baton's sole input mechanism — it sleeps until an event arrives, processes it, checks for dispatchable sheets, and sleeps again.
Events come from five sources:
- Musicians — sheet execution results (SheetAttemptResult, SheetSkipped)
- Timer wheel — scheduled future events (RetryDue, RateLimitExpired, StaleCheck, CronTick, JobTimeout, EscalationTimeout, PacingComplete)
- External commands — CLI/IPC/dashboard (PauseJob, ResumeJob, CancelJob, ConfigReloaded, EscalationResolved, ShutdownRequested)
- Observer — runtime monitoring (ProcessExited, ResourceAnomaly)
- Internal — dispatch coordination (DispatchRetry)
Design decisions:
- All events are frozen dataclasses — immutable after creation, safe to pass between asyncio tasks without copying.
- BatonEvent is the union type used for inbox typing.
- Events carry only the data needed for the baton to make a decision. They do not carry the full execution output (that's in CheckpointState).
- Events are compatible with the existing ObserverEvent TypedDict format
via the
to_observer_event()method for EventBus integration.
See: docs/plans/2026-03-26-baton-design.md for the full architecture.
Attributes¶
Classes¶
SheetAttemptResult
dataclass
¶
SheetAttemptResult(job_id, sheet_num, instrument_name, attempt, execution_success=True, exit_code=None, duration_seconds=0.0, validations_passed=0, validations_total=0, validation_pass_rate=0.0, validation_details=None, error_classification=None, error_message=None, rate_limited=False, rate_limit_wait_seconds=None, cost_usd=0.0, input_tokens=0, output_tokens=0, model_used=None, stdout_tail='', stderr_tail='', timestamp=time())
A musician reports the result of a single sheet attempt.
This is the central event in the baton's event loop. The musician plays once and reports in full detail. The conductor (baton) decides what happens next — retry, completion mode, healing, escalation, or accept.
Rate limits are NOT failures. When rate_limited is True, the baton
re-queues the sheet for when the instrument recovers. No retry budget
is consumed.
Attributes¶
validation_pass_rate
class-attribute
instance-attribute
¶
Percentage of validations that passed (0.0-100.0).
CRITICAL CONTRACT (F-018): Set to 100.0 when execution succeeds with no validation rules OR when all validations pass. The baton treats the default (0.0) as "all validations failed" and will retry.
A musician that reports execution_success=True with
validations_total=0 but leaves this at 0.0 will trigger
unnecessary retries until max_retries is exhausted.
rate_limit_wait_seconds
class-attribute
instance-attribute
¶
Parsed wait duration from the API's rate limit error message.
When set, the baton uses this instead of the default 60s for scheduling the recovery timer. This is the actual duration the API told us to wait.
SheetSkipped
dataclass
¶
A sheet was skipped due to skip_when condition or start_sheet override.
The baton propagates skip state to dependents — downstream sheets that depend on a skipped sheet receive a skip sentinel, not empty string.
SheetDispatched
dataclass
¶
A sheet has been dispatched to a musician for execution.
Emitted by dispatch_ready() after the dispatch callback succeeds. The baton sets DISPATCHED status and records the dispatch timestamp.
RateLimitHit
dataclass
¶
An instrument hit a rate limit. NOT a failure — a tempo change.
The baton marks the instrument as rate-limited and schedules a timer for recovery. Sheets targeting this instrument move to waiting state. Other instruments are completely unaffected.
RateLimitExpired
dataclass
¶
Timer fired — check if the rate-limited instrument is available again.
If the instrument is still unavailable, the baton schedules another timer. If available, sheets waiting on this instrument become ready.
RetryDue
dataclass
¶
Timer fired — a previously failed sheet is ready for retry.
The baton moves the sheet from retry-scheduled to ready state. The next dispatch cycle will pick it up.
StaleCheck
dataclass
¶
Timer fired — check if a running sheet has gone stale.
If no output progress has been received within the configured idle timeout, the baton kills the stale sheet and reschedules or fails it.
CronTick
dataclass
¶
Timer fired — a cron-scheduled job should be submitted.
The baton submits the configured score as a new job and schedules the next tick. If a previous run is still active, this tick is skipped.
JobTimeout
dataclass
¶
Timer fired — a job has exceeded its wall-clock time limit.
The baton cancels all remaining sheets for this job.
PacingComplete
dataclass
¶
Timer fired — the inter-sheet pacing delay for a job has elapsed.
The baton clears the pacing flag, allowing the next sheet to dispatch.
Implements pause_between_sheets_seconds from score config.
EscalationNeeded
dataclass
¶
A sheet execution requires composer judgment — enter fermata.
The baton pauses the job's dispatch and notifies the composer (human or AI) via configured channels. A timeout timer is scheduled.
EscalationResolved
dataclass
¶
The composer has made a decision on a fermata.
The baton applies the decision and resumes dispatching for the job.
Arrives via IPC (job.resolve_escalation method).
EscalationTimeout
dataclass
¶
Timer fired — no escalation response received within the deadline.
The baton defaults to the safe action: fail the sheet (not the job) and resume dispatching for other sheets.
PauseJob
dataclass
¶
Pause dispatching for a job. In-flight sheets continue to completion.
No new sheets are dispatched until ResumeJob is received. Retry timers are preserved — when resumed, scheduled retries fire normally.
ResumeJob
dataclass
¶
Resume dispatching for a paused job, optionally with new config.
When new_config is provided, pending sheets are rebuilt from the
new config. Completed sheets are preserved. Failed sheets being
retried use the new config for the retry.
CancelJob
dataclass
¶
Cancel all sheets for a job and deregister it from the baton.
In-flight sheet tasks are cancelled. The job is marked as cancelled in CheckpointState.
ConfigReloaded
dataclass
¶
Config has changed for a job (SIGHUP, mzt modify, resume -c).
The baton rebuilds pending sheets from the new config. Completed sheets are preserved. Cost limits may be reset if they changed.
ShutdownRequested
dataclass
¶
The conductor is shutting down (SIGTERM, mzt stop).
When graceful is True, the baton waits for in-flight sheets
to complete (up to the configured drain timeout) before stopping.
When False, sheets are cancelled immediately.
ProcessExited
dataclass
¶
Observer detected that a backend process died unexpectedly.
The baton checks if this was a sheet's backend process and, if so, marks the sheet as crashed — faster than waiting for timeout.
ResourceAnomaly
dataclass
¶
Observer/monitor detected a resource pressure event.
Critical severity triggers backpressure — the baton stops dispatching new sheets and lets running sheets drain.
InstrumentFallback
dataclass
¶
A sheet's instrument was switched to a fallback.
Emitted when the baton moves a sheet from one instrument to the next in its fallback chain. Reasons:
"unavailable"— instrument not installed, binary missing, circuit breaker open. Immediate fallback at dispatch time."rate_limit_exhausted"— all retries on the current instrument hit rate limits with no recovery. Fallback after retry exhaustion.
This is an INFO-level event. Fallback is the system working correctly, not failing. Each fallback instrument gets a fresh retry budget.
A2ATaskSubmitted
dataclass
¶
A2ATaskSubmitted(job_id, sheet_num, target_agent, task_description, context=dict(), timestamp=time())
An agent requests a task from another running agent.
The conductor routes the task to the target agent's inbox, persisted in the target's job state. The target picks it up on their next A2A-enabled sheet.
A2ATaskRouted
dataclass
¶
The conductor has delivered a task to the target agent's inbox.
Confirms that the task is persisted and waiting for the target agent to process on their next relevant sheet.
A2ATaskCompleted
dataclass
¶
A delegated task has been completed with artifacts.
Results are routed back to the requesting agent's inbox. The requester picks them up on their next relevant sheet.
A2ATaskFailed
dataclass
¶
A delegated task could not be fulfilled.
The requesting agent is notified with the reason for failure so they can decide whether to retry, delegate elsewhere, or handle it themselves.
DispatchRetry
dataclass
¶
Internal signal to retry dispatch after a backpressure delay.
When the baton encounters backpressure during dispatch, it schedules this event via the timer wheel rather than blocking.
CircuitBreakerRecovery
dataclass
¶
Timer fired — check if a circuit-broken instrument can accept a probe.
When a circuit breaker trips OPEN, the baton schedules this event via the timer wheel. On fire, the instrument transitions from OPEN to HALF_OPEN, allowing one probe request through. The next dispatch cycle picks up any PENDING sheets blocked by the dead-ended fallback chain.
If the probe succeeds, the breaker closes. If it fails, the breaker reopens and a new recovery timer is scheduled with increased backoff.
GH#169: Without this, sheets whose entire fallback chain is circuit-broken stay PENDING forever — the score appears RUNNING but is dead.
Functions¶
to_observer_event
¶
Convert a BatonEvent to the ObserverEvent TypedDict format.
The baton publishes events to the EventBus so that the dashboard,
learning hub, and notification system can consume them. Baton events
use the baton.* namespace to distinguish from runner events.
Returns a dict matching the ObserverEvent TypedDict shape:
{job_id, sheet_num, event, data, timestamp}
Source code in src/marianne/daemon/baton/events.py
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | |