| 459 | } |
| 460 | |
| 461 | fn transition_from_idle(event: Event) -> TransitionResult { |
| 462 | match event { |
| 463 | // Agent starts a turn → go active |
| 464 | Event::TurnStart => { |
| 465 | TransitionResult::with_actions(Phase::Active, vec![Action::UpdateInteraction]) |
| 466 | } |
| 467 | |
| 468 | // Turn end while idle → still attempt to record. |
| 469 | // OpenCode's plugin fires session.idle (TurnEnd) without a preceding |
| 470 | // TurnStart when the bus event ordering doesn't guarantee it. |
| 471 | // Rather than silently dropping the turn, attempt a record — if |
| 472 | // the working copy is clean, record_turn returns EmptyTurn harmlessly. |
| 473 | Event::TurnEnd => TransitionResult::with_actions( |
| 474 | Phase::Idle, |
| 475 | vec![Action::RecordIfChanged, Action::UpdateInteraction], |
| 476 | ), |
| 477 | |
| 478 | // A change was recorded while idle (user manually recorded) → record |
| 479 | Event::Recorded => TransitionResult::with_actions( |
| 480 | Phase::Idle, |
| 481 | vec![Action::RecordTurn, Action::UpdateInteraction], |
| 482 | ), |
| 483 | |
| 484 | // Session started while idle → no-op (already condensable) |
| 485 | Event::SessionStart => TransitionResult::noop(Phase::Idle), |
| 486 | |
| 487 | // Session stopped while idle → end |
| 488 | Event::SessionStop => { |
| 489 | TransitionResult::with_actions(Phase::Ended, vec![Action::UpdateInteraction]) |
| 490 | } |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | fn transition_from_active(event: Event) -> TransitionResult { |
| 495 | match event { |