Skip to content

feat(core): soft interrupts — steer a running turn without cancelling it (#377, 1/2) - #391

Merged
ajianaz merged 4 commits into
developfrom
feat/soft-interrupt-core
Oct 16, 2026
Merged

ajianaz merged 4 commits into
developfrom
feat/soft-interrupt-core

Conversation

@ajianaz

@ajianaz ajianaz commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

What

Part 1 of 2 of soft interrupts: the core mechanism. Host entry points (serve REST, MCP tool) follow in part 2.

Why

#377. Cancel loses the turn's partial work; the owner needs to steer a running session at a safe point instead.

Changes

  • interrupt.rs (new): bounded InterruptQueue (16 pending, 8 KiB per message; blank or oversized text is refused, never truncated).
  • cancel.rs: the queue rides on the session's CancelToken (the per-session turn handle every host already shares), so no signature in the turn API changes and default tokens are unchanged.
  • turn.rs: the loop drains the queue at its safe point (tool settled, next provider call not started) and commits each message as an attributed user-role entry (interrupt: true, attribution in the text). An interrupt that lands while a provider call is in flight supersedes that output before it takes effect: a final answer yields to any pending interrupt, a not-yet-started tool call only to an urgent one. The withdrawn output was never committed, so no intent is written and no tool_use is left without its tool_result; a durable superseded by owner interrupt error entry records the drop.
  • Interrupt entries never open a turn (turn-end gate start, usage_report turn stats, tole status turn count).
  • docs/architecture.md, CHANGELOG.

Design note

The loop issues one tool call per provider step, so there is no batch of remaining tools to skip: "urgent" withdraws the call the model just asked for, before its intent exists. An interrupt arriving after a turn's last safe point waits for the next turn's first.

Testing

  • 6 integration tests (mock provider/tool as the second client): delivery order and attribution, urgent withdrawal with no orphan intent and a durable record, normal interrupt keeps the call, final answer superseded, queued-before-turn ordering, no-interrupt path unchanged. 3 queue unit tests; 1 turn-stats test.
  • fmt, clippy -D warnings, cargo test --workspace pass; cora review --staged clean.
  • Not done: live E2E from a second client (needs the host entry points in part 2 and a real provider).

Refs #377

@github-actions

Copy link
Copy Markdown

🔍 Cora AI Code Review

✅ No issues found. Code looks good!


Review powered by cora-code · BYOK · MIT

@ajianaz
ajianaz merged commit bd2e1ff into develop Oct 16, 2026
17 checks passed
@ajianaz
ajianaz deleted the feat/soft-interrupt-core branch October 16, 2026 04:47
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.

1 participant