chore(test): pin asyncio_default_fixture_loop_scope to function#74
Merged
Merged
Conversation
Silences the deprecation warning that pytest-asyncio emits on every test run: PytestDeprecationWarning: The configuration option "asyncio_default_fixture_loop_scope" is unset. The event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Pin the default to ``function`` explicitly. Matches the future pytest-asyncio default and silences the warning. Re-port of closed PR #51 (was on stale base ~8870 deletions behind current main). Same one-line fix; fresh against `f9ec4ea`.
6 tasks
mikemolinet
added a commit
that referenced
this pull request
May 11, 2026
…parity port of cueapi/cueapi#623) (#77) Re-port of closed [PR #46](#46) which was on a stale base ~8900 deletions behind main. Fresh against current main HEAD. Closes §13 / Phase 12.1.7 — messages-side complement to the cue-fire send_at shipped in PR #618 (which still needs its own re-port). ## What lands - **alembic/versions/030_message_send_at.py** (renumbered from private's 047) Adds `messages.send_at TIMESTAMPTZ NULL` + partial index `ix_messages_send_at` (WHERE send_at IS NOT NULL) built CONCURRENTLY so the index creation doesn't take an ACCESS EXCLUSIVE lock on the messages table during deploy. Existing rows default to NULL = "send now". - **app/models/message.py** — adds `send_at` Column. - **app/schemas/message.py** — `send_at: Optional[datetime]` on MessageCreate + MessageResponse. - **app/routers/messages.py** — passes `send_at=body.send_at` into `create_message`. - **app/services/inbox_service.py** — gates inbox query AND queued→delivered transition UPDATE with `send_at IS NULL OR send_at <= now()`. Scheduled messages are invisible until their time; the atomic poll-fetch transition skips them too. - **app/services/message_service.py** — `create_message` plumbs `send_at` into both `Message.send_at` and `DispatchOutbox.scheduled_at`. Past timestamps are forgiving fallback (treated as send-now). `to_response_dict` surfaces the persisted value. - **tests/test_message_send_at.py** — 7 new tests verbatim from private cueapi covering all 7 semantic paths (omitted, future-invisible, outbox-scheduled, past-fallback, becomes-visible- after-pass, sender-view-shows-it, invalid-timestamp). - **parity-manifest.json** — new entry for migration 030 under `message-send-at-port (private #623)`. ## Wire format `send_at` flows in the BODY of `POST /v1/messages` (server contract: `MessageCreate.send_at`). Same shape as cue-fire `send_at` (PR #618). NULL = send now (default). Future timestamp = inbox-gate + DispatchOutbox.scheduled_at. Past timestamp = forgiving send-now. ## Tests 7/7 new tests pass locally. Full local suite: 836 passed + 18 xfailed (pre-existing) + 3 skipped. Zero regressions. ## Sibling ports - cli, mcp, python, action sides shipped via session 2 (2026-05-10): cueapi-cli #48, cueapi-mcp #33, cueapi-python (private), cueapi-action #12. This is the cueapi-core (OSS server) side that was still missing. ## Re-port note Re-port of closed PR #46. That branch was ~8900 deletions behind main; fresh port against current main HEAD (after PR #74 + #75 merged earlier in this session).
6 tasks
mikemolinet
added a commit
that referenced
this pull request
May 11, 2026
…arity port of cueapi/cueapi#618) (#78) Re-port of closed [PR #45](#45) which was on a stale base ~8880 deletions behind main. Fresh against current main HEAD. Closes §13 / Phase 12.1.7 (cue side). Optional `send_at` timestamp on the fire body delays dispatch until the time elapses. ## Why this is small The dispatch loop in `worker/poller.py:dispatch_outbox` already gates on `DispatchOutbox.scheduled_at` (added in slice 3b for messages, just merged via PR #77 for messages send_at). This PR plumbs `send_at` from FireRequest through to `Execution.scheduled_for` and `DispatchOutbox.scheduled_at`. No poller changes required. ## What lands - **app/schemas/cue.py** — new `FireRequest` Pydantic model with optional `send_at: Optional[datetime]` field. - **app/routers/cues.py** — `fire_cue` endpoint accepts optional `body: Optional[FireRequest] = None`. Computes effective `scheduled_for` (future send_at → that timestamp; past or omitted → now). Sets `DispatchOutbox.scheduled_at` on the outbox row when scheduled. - **tests/test_fire_send_at.py** — 6 tests verbatim from private (5 active + 1 skipped). The skipped test relies on `payload_override` which is a separate parity port (cueapi/cueapi#589/#590 — not yet in cueapi-core); marked with a `@pytest.mark.skip` + reason pointer so it un-skips automatically when those ports land. ## Semantics (per private cueapi#618) - `send_at` omitted (or no body) → existing behavior: dispatch immediately, outbox.scheduled_at = NULL. - `send_at` in the future → execution.scheduled_for = send_at, outbox.scheduled_at = send_at, dispatcher gates until that time. - `send_at` in the past → forgiving fallback to "fire now". No error. Same shape as send_at omitted. Idempotent — caller doesn't have to worry about clock skew or being a few ms late. ## Tests 5 new tests pass (omitted, future-delays-dispatch, past-falls-back, invalid-timestamp-422, worker-transport-no-outbox). 1 skipped (composes-with-payload-override, depends on PR #589/#590 port). Full local suite: 834 passed + 18 xfailed (pre-existing) + 4 skipped (1 new, 3 pre-existing). Zero regressions. ## Re-port note Re-port of closed PR #45. Fresh against current main after PR #74 + #75 + #77 merged earlier in this session.
Merged
6 tasks
mikemolinet
added a commit
that referenced
this pull request
May 11, 2026
…ed_at on list endpoint (#79) Re-port of closed [PR #48](#48) which was on a stale base ~8870 deletions behind main. Fresh against current main HEAD via direct patch from the old branch's commit (c05518c). Adds query-side enrichment to ``GET /v1/executions``: - ``worker_id=`` — filter to executions claimed by a specific worker (Execution.claimed_by_worker) - ``status__in=foo,bar,baz`` — comma-separated multi-status filter. Mutex with ``status=``; 400 conflicting_filters if both passed. - Response gains ``oldest_claimed_at`` — earliest ``claimed_at`` over the filtered set, or null when count=0. Unblocks dashboard/menubar "oldest pending: 5m" rendering without a follow-up query. ## Use cases - **Menubar pending counter**: fetch ``pending,delivering,retry_ready`` in one round trip (status__in), get total + oldest_claimed_at to render "3 in flight, oldest claimed 8m ago". - **Worker health dashboard**: filter by worker_id to scope to one worker's claims; see how stale their oldest claim is. ## Tests 3 new tests in TestListExecutions: - worker_id scoping + oldest_claimed_at value reflects earliest claimed_at over filtered set - status__in union + status/status__in mutex 400 - null oldest_claimed_at on empty filtered set 31/31 in test_execution_parity.py green. Full local suite: zero regressions. ## Re-port note Re-port of closed PR #48 (commit c05518c). Branch was ~8870 deletions behind main; fresh against current main after PR #74/#75/#76/#77/#78 merged earlier in this session. Patch applied cleanly from c05518c to current main — the patch only touches list_executions endpoint, which has remained additive (cueapi-core added outcome_state filter since the branch was cut; this PR is compatible).
7 tasks
mikemolinet
added a commit
that referenced
this pull request
May 11, 2026
…ueapi/cueapi#630) (#80) Re-port of closed [PR #47](#47) which was on a stale base ~8880 deletions behind main. Fresh against current main HEAD. Phase A of the Agent Directory productization. Eliminates the failure mode where agents had to remember 6+ fields per recipient AND had no way to discover the live roster. ## What lands - **GET /v1/agents/roster** — display-optimized snapshot for prompt- injection at session-boot. Distinct from the existing management surface (GET /v1/agents): - Always-full list (no pagination) - Drops opaque IDs / secrets / timestamps / tenancy metadata - Adds derived ``online``, ``last_seen_relative``, ``preferred_contact`` - Always excludes soft-deleted agents - Weak ETag + ``If-None-Match`` → 304 Not Modified for poll efficiency - ETag bucketed to 5-min windows so quiet periods produce stable hashes - ``Cache-Control: private, max-age=300`` matches derivation buckets - **Migration 031** (renumbered from private's 048) — adds ``agents.last_seen_at TIMESTAMPTZ NULL``. Nullable, no backfill. - **Hot-path hooks** write ``last_seen_at = now()``: - ``create_message`` — sender's agent (in same tx via touch_last_seen) - ``list_inbox`` — recipient's agent, on EVERY poll (via _bump_last_seen_stmt). Even when no queued messages exist, the poll proves activity. - **Online derivation** (server-computed in ``list_roster``): - within 5 min → ``online`` - within 30 min → ``away`` - older or NULL → ``offline`` - Caller override wins: PATCHed status=away/offline keeps that override regardless of recent activity ## Pure helpers (for unit-testability — pytest-cov + ASGI issue) - ``_build_roster_entry(agent, now)`` in agent_service.py: ORM Agent → (entry_dict, etag_part_string) - ``_compute_roster_etag(parts)`` in agent_service.py: list → weak ETag - ``_derive_online_state(now, last_seen_at, asserted_status)`` → (online_bool, derived_status) - ``_format_relative(now, last_seen_at)`` → "active now" / "5m ago" / ... - ``_bucketed_seen(last_seen_at)`` → string for ETag stability - ``_bump_last_seen_stmt(agent_id, now)`` in inbox_service.py: SQLAlchemy UPDATE statement - ``_etag_matches(if_none_match, server_etag)`` in agents router: conditional GET predicate ## Tests 27 new tests in tests/test_agent_roster.py (verbatim from private): shape verification, hot-path hooks (sender + recipient), derivation correctness across all 3 buckets, caller-asserted status override, soft-delete exclusion, preferred_contact derivation, last_seen_relative formatting, ETag 304 handling, ETag changes when roster mutates, pure-helper unit tests. 27/27 pass locally. Full local suite: 890 passed + 18 xfailed (pre-existing) + 4 skipped. Zero regressions. ## Re-port note Re-port of closed PR #47. Fresh against current main after PR #74 + #75 + #76 + #77 + #78 + #79 merged earlier in this session.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
One-line addition to
pytest.inisilencing the pytest-asyncio deprecation warning that fires on every test run.What landed
[pytest] asyncio_mode = auto +asyncio_default_fixture_loop_scope = functionWhy
pytest-asyncio currently warns:
Pinning to
functionexplicitly matches the future pytest-asyncio default and silences the warning. Zero behavior change today.(There's also a separate
event_loop-fixture deprecation warning intests/conftest.py:37— that's a different fix, not this PR.)Re-port note
Re-port of closed PR #51. That PR was on a stale base ~8870 deletions behind current main; closed it earlier today and opened this fresh PR against current main HEAD (
f9ec4ea). Same one-line fix.Test plan
asyncio_default_fixture_loop_scopeconfig option🤖 Generated with Claude Code