Skip to content

feat(telegram): ADR-0020 slice 1a TurnGate + mid-run steer - #170

Merged
chinkan merged 2 commits into
mainfrom
feat/mid-run-queue
Oct 7, 2026
Merged

chinkan merged 2 commits into
mainfrom
feat/mid-run-queue

Conversation

@chinkan

@chinkan chinkan commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Summary

ADR-0020 slice 1a: mid-run message queue for Telegram user turns.

  • TurnGate per session_key(bot_id, user_id): at most one active turn; FIFO pending cap 10; full → QUEUE_FULL text (never silent drop).
  • Telegram ingress: submit → on Start spawn a loop that runs run_telegram_user_turn then finish → Next::User / StepLimit / Idle | Scheduled; on Accepted react 👀; on Full reply with the queue-full sentence.
  • Steer drains A/B in loop_runner via SteerFn / with_steer; queued text injected with a [Steer] prefix.
  • /stop: cancel processing and turn_gate.clear (report how many queued messages were cleared).
  • Removed dead ConversationManager::apply_steer and pending_injections path; lib.rs exports turn_gate.
  • Injector harness waits for gate idle after chat drives (spawn is intentional so the dispatcher stays free).

Out of scope (later slices)

  • 1b — schedule-through-gate coordination
  • 1c — voice / media on the queue path
  • 2 — portal 202 / generation identity alignment

Note / deviation

cancel_token_registry is kept: the gate serializes turns per key, so there is still one cancel token per key.

Refs: ADR-0020

Test plan / QA matrix

  • Unit: turn_gate module tests + tests/mid_run_steer.rs
  • cargo fmt --check
  • cargo clippy --locked --all-targets -- -D warnings
  • env -u RUSTFOX_GOOGLE_OAUTH_CLIENT_ID cargo test --locked (942 passed / 0 failed)
  • Manual Telegram:
    • Mid-run second message gets 👀 and steers the active turn
    • Queue-full text when 10 are already waiting
    • /stop cancels and clears the queue
    • Step-limit sentence once, then clear / continue behavior as ADR-0020 Q6

Introduce TurnGate (session_key, cap 10, QUEUE_FULL) so Telegram user
turns serialize per key: submit → spawn loop → finish → User / StepLimit
/ Idle|Scheduled. Mid-run messages get 👀 Accepted and steer via drain
A/B with a [Steer] prefix; /stop cancels and clears the queue.

Wire SteerFn into loop_runner, drop dead apply_steer / pending_injections,
and keep cancel_token_registry (gate serializes → one token per key).
Update the Telegram Update injector to await gate idle after chat drives.

chinkan commented Oct 7, 2026

Copy link
Copy Markdown
Owner Author

TL ACCEPT — ADR-0020 slice 1a @ 301568c

Reviewed tip 301568c (base 4f293f6) against ADR-0020 slice 1a only. Product GO already on record.

Passes

  • TurnGate per session_key(bot_id, user_id): FIFO cap 10; QUEUE_FULL English refusal (not silent drop); text reply path is not gated by fully_silent.
  • Telegram: submit → spawn turn (dispatcher free); Accepted → setMessageReaction(👀) only; reaction failure → warn!, no ack bubble.
  • Steer drains A/B in AgenticLoop via with_steer; injection prefixed [Steer]; scheduled / /mode queue do not attach steer (pending left for finish).
  • /stop: cancel_processing + turn_gate.clear with N; does not discard waiting scheduled tickets.
  • Max-iterations: auto-continue once; second hit → locked step_limit_text(N); idle with queue kept.
  • Dead pending_injections / apply_steer removed; cancel_token_registry kept (PO-ok).
  • Unit turn_gate + tests/mid_run_steer.rs; CI Test green (~942); fmt/clippy green.

Out of scope (correctly left out)

  • 1b schedule-through-gate (begin_scheduled not wired; parallel schedule+user still possible).
  • 1c voice/media queue path; slice 2 portal.

Non-blocking follow-up (do not block 1a merge)

  • Spawn-loop restore_pending(rest) under /mode queue can start leftovers as one-message-per-turn instead of one combined turn (ADR Decision 5). Default Steer path is fine; please fix when touching the spawn loop / before leaning on queue mode in QA.

No merge/tag from TL. Same-account standing → this is the ACCEPT record (issue comment), not the Approve button.

Comment thread tests/telegram_update_injector.rs Fixed
CodeQL rust/cleartext-logging flagged interpolating session_key into
panic! in the Telegram injector harness (alert #26). Message no longer
embeds the key.

chinkan commented Oct 7, 2026

Copy link
Copy Markdown
Owner Author

TL ACCEPT — tip c2e7353 (re-ACCEPT after CodeQL #26 fix)

Delta from 301568c: tests/telegram_update_injector.rs wait_turn_idle panic no longer interpolates session_key (panic!("turn gate still active after 5s")). Matches PO/QA ask — no dismiss needed.

Prior TL ACCEPT on slice 1a still stands for the rest of the PR. Merge when QA GO (CI green on this tip + manual Telegram) lands. No tag.

@chinkan
chinkan merged commit ed2b9d9 into main Oct 7, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants