Skip to content

feat: add task deadlines and cancellation#49

Merged
ebarti merged 4 commits into
mainfrom
agent/stack-09-deadlines-cancellation
Jul 10, 2026
Merged

feat: add task deadlines and cancellation#49
ebarti merged 4 commits into
mainfrom
agent/stack-09-deadlines-cancellation

Conversation

@ebarti

@ebarti ebarti commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Stack

What this fixes

The runtime protocol advertised cancellation, but every provider adapter implemented it as a no-op, and tasks had no portable execution deadline. That left callers unable to bound startup, process-reuse queueing, or in-flight provider work.

Changes

  • add keyword-only, timezone-aware AgentTask.deadline
  • add AgentKit.run(timeout=...) as a finite non-negative seconds/timedelta convenience
  • add AgentTaskTimeoutError and FinishReason.TIMED_OUT
  • add immutable CancellationReceipt and explicit cancellation dispositions
  • make built-in Claude, Codex, Antigravity, and fake runtimes cancellation-aware
  • make AgentKit.cancel() target active cached runtimes without constructing new ones
  • preserve legacy third-party runtimes whose cancel() returns None
  • document cancellation's non-rollback semantics

Adversarial race hardening

Independent reproductions found concurrency defects beyond the initial green suite. Follow-up commits now:

  • bind cancellation to the exact asyncio task generation
  • reserve same-id tombstones while legacy task-id hooks settle, preventing ABA cancellation
  • remove cancellable lock windows from registration/unregistration
  • keep cancellation effective if the AgentKit.cancel() caller is cancelled
  • make completion-race receipts truthful
  • make timeout causality win once the deadline fires and emit at most one terminal
  • skip misleading started events for already-expired tasks
  • give provider/operation teardown a bounded five-second grace period
  • quarantine runtime instances while detached cleanup remains pending, rejecting overlap and recovering automatically when cleanup settles
  • validate deadline runtime types deliberately instead of leaking AttributeError

Verification

  • all-extras full suite: 418 passed, 3 skipped
  • core-only full suite: 409 passed, 12 skipped
  • all-extras coverage: 90.33% (minimum 85%)
  • focused race/control suite: 22 passed
  • final independent quarantine reproductions: 3 passed; no pending-task warnings
  • uv run ruff check .
  • strict mypy
  • uv lock --check
  • uv build
  • git diff --check

Stack health

All 11 required GitHub checks pass on bcd080c; the opt-in upstream-latest workflow is skipped by design.

@ebarti ebarti force-pushed the agent/stack-08-provider-native-models branch from 1fe7c21 to 530d4f6 Compare July 10, 2026 22:47
ebarti added a commit that referenced this pull request Jul 10, 2026
## What

- delegates the no-override model choice to each provider instead of
pinning library-owned names
- preserves one precedence chain: task field > legacy metadata >
constructor override > provider-native
- omits vendor model kwargs when selection is provider-native
- records `model_source` on every provider result and records `model`
only when known
- keeps `default_model=` as an explicit migration override
- makes configured model allow-lists fail closed when provider-native
selection cannot be verified

## Why

Hard-coded adapter defaults age faster than the SDK and can override
supported provider configuration. The SDK-evolution docs already
described Claude and Antigravity as provider-native, but the adapters
silently forced stale model names.

## Root cause

Model resolution treated the library constructor default as mandatory
rather than an optional override, and result metadata could not
distinguish task, metadata, constructor, and provider-native selection.

## Compatibility

This is an intentional pre-1.0 behavior change. Applications that need
the prior pin can pass the same value through `default_model=`; task and
metadata overrides keep their existing precedence.

## Checks

- `ruff check src tests`
- strict `mypy`
- full all-extras suite: 396 passed, 3 skipped
- model-policy coverage run: 356 passed, 3 skipped; 91.00% coverage
- installed SDK contracts: 23 passed
- `uv lock --check`
- `uv build`

## Stack

- Base: #47
- Next: #49
Base automatically changed from agent/stack-08-provider-native-models to main July 10, 2026 22:48
@ebarti ebarti force-pushed the agent/stack-09-deadlines-cancellation branch from bcd080c to dbca5cd Compare July 10, 2026 22:48
@ebarti ebarti marked this pull request as ready for review July 10, 2026 22:48
@ebarti ebarti merged commit 7e611e5 into main Jul 10, 2026
11 checks passed
@ebarti ebarti deleted the agent/stack-09-deadlines-cancellation branch July 10, 2026 22:49
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