Skip to content

feat(sessions): deliver durable Stop directly to the runner - #6503

Merged
mmabrouk merged 39 commits into
feat/session-controlfrom
feat/session-durable-cancel
Sep 4, 2026
Merged

feat(sessions): deliver durable Stop directly to the runner#6503
mmabrouk merged 39 commits into
feat/session-controlfrom
feat/session-durable-cancel

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Sep 2, 2026

Copy link
Copy Markdown
Member

Agent-generated, low weight. Draft. Do not merge before Mahmoud reviews it.

Implements the Spike B design with the direct adapter: the session_commands table, POST /sessions/{id}/cancel with an optional expected_execution_id, the control-delivery port, the runner POST /cancel beside /kill, the outcome route, and settlement that releases running under the owner check and leaves alive to its TTL. Long polling is designed (PR #6497) and parked in Linear AGE-4253. Heartbeats stay a health and ownership signal. Stacked on Spike A (PR #6496).

Evidence

Date Provider Harness Commit Scenario Result Timing
2026-09-02 local Pi 58bec4d382 Stop during a 60 s tool, then continue command applied/stopped, park-cancelled, next message recalled the codeword request to abort 82 ms, harness confirmed 106 ms, settled 126 ms, parked 993 ms
2026-09-02 local Pi 58bec4d382 Stop when idle; stale expected_execution_id; two Stops; Stop on a parked approval obsolete 200; 409 nothing written; one command; interaction cancelled, environment kept, resume warm
2026-09-03 local Pi 58bec4d382 after settlement, sample the row for 3 min row kept is_running: true (the runner's final beat landed 0.88 s after settlement and the tombstone check refused it before the mirror write); the collection query every liveness poll drives is served from Postgres alone
2026-09-03 local Pi 76e4b1368b same, with mirror_liveness at settlement is_running: false at Stop plus 0.15 s, is_alive: true; warm resume 2.01 s inside the park window against a 14.16 s cold rebuild after it
2026-09-03 local and Daytona Pi and Claude Code 9110c08000 (integration) Stop naming its turn while the turn waits on an approval 409 four of four (expectation compared against running only; a parked approval holds the turn in alive); the same Stop without an id cancelled the gate
2026-09-03 local Pi 89d7c7c90d same 202, gate pending to cancelled; a stale id still 409, naming the turn that would have been stopped
2026-09-03 local and Daytona Pi 9110c08000 Stop during output, outcome report 409 on four of nine turns; the command sat claimed until the watchdog settled it lost (one case exactly 120 s)
2026-09-03 local Pi 89d7c7c90d same the runner's report is accepted whether the row is pending or claimed; the duplicate gets 409
2026-09-03 local Pi 89d7c7c90d Stop fired the instant the prompt settles, before teardown the applier aborted a live registry entry, the aborted signal made the park rule refuse (no-park:end_turn), cold rebuild 7.21 s
2026-09-03 local Pi 38cbc92201 same run marked settled at prompt settle, applier no-op, command obsolete/not_running, parked, warm hit-continue 1.91 s
2026-09-03 local Pi 76e4b1368b Stop, then docker restart the runner, then continue refused until the Redis owner lease (120 s) expired: the runner never releases its owner claim at shutdown and a restarted runner has a new replica id; deleting only the owner key admitted the next message at once fix on the Spike A stack, in progress

Trade-off taken on 38cbc92201: past teardown, the API now discriminates lost from not_running on the running key instead of the heartbeat, so in a multi-runner deployment a Stop misrouted to a replica that holds a parked approval settles not_running instead of lost. Multi-replica direct delivery is not version one; open question 8 in the report.

Tests

  • API session unit tests in the api container against live Postgres: 564 pass (head 38cbc92201).
  • cd services/runner && pnpm test: 2671 pass, 160 files (run pnpm run build:extension once in a fresh worktree first).
  • @agenta/entities 1468, @agenta/navigation 46, @agenta/mobile 144.
  • uvx ruff@0.15.12 format and check: clean. pnpm lint-fix: clean.

Branch head

38cbc92201 on feat/session-durable-cancel, base spike/session-cancel-warm. Reports: slice-durable-cancel.md on this branch; evidence-2026-09-03/post-stop-mirror.md, post-stop-liveness.md, and daytona-pi-claude.md on PR #6505.

https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV

Restack of 2026-09-04

This PR now carries the rollback switch itself, so it is safe on its own: AGENTA_SESSIONS_DURABLE_STOP (default off) in env.py; with it off the cancel route returns the exact legacy response and takes the heartbeat-carried Stop, and no session_commands row is written. Commits 50bffdc8ef and e9858e64ac moved down from PR #6501. Also 5a66bf0e12 narrows the runner-control auth exemption from /sessions/control/ to /sessions/control/commands/, so a session whose id is literally control still needs project auth (a whole-PR review finding). Head 5a66bf0e12; API sessions suite 568 passed. Agent-generated, low weight.

Cancelled interaction record (2026-09-04, afternoon)

The browser pass showed an approval card that stayed pending after a Stop, because the cancel updated the interaction row and published a notice but wrote no transcript record. Commit e4cbd64ac9 writes one cancelled interaction record per cancelled interaction (deterministic id, identifiers only, published after commit); a later answer gets 409 "Interaction is no longer pending". Reviewed: passes. Known item, non-blocking: the desktop clears the card from the interaction row state, and its record handler ignores the new record's outcome: cancelled shape; a records-only consumer would need the client handler aligned (client side, PR #6504). The record append is a separate transaction from the cancel commit, as on the normal-answer path.

@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agenta-documentation Ready Ready Preview Sep 4, 2026 7:26pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • release/.*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: e547d63d-60ca-4df2-8b98-a9e9f753d5dd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 7d9ba61a-653e-4a63-b809-75d469ee8856

📥 Commits

Reviewing files that changed from the base of the PR and between 69db342 and cd21450.

⛔ Files ignored due to path filters (13)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/runner/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • services/uv.lock is excluded by !**/*.lock
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/CancelSessionExecutionRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionCancelRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionStream.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/index.ts is excluded by !**/generated/**
📒 Files selected for processing (172)
  • .agents/skills/agent-release-gate/SKILL.md
  • .agents/skills/agent-release-gate/resources/path_triggers.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • .agents/skills/agent-release-gate/resources/session_control.py
  • .agents/skills/agent-release-gate/resources/test_qa_product_concurrency.py
  • .agents/skills/agent-release-gate/resources/test_session_control.py
  • .all-contributorsrc
  • README.md
  • api/ee/src/dbs/postgres/sessions/records/dao.py
  • api/entrypoints/routers.py
  • api/entrypoints/worker_streams.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/apis/fastapi/evaluations/router.py
  • api/oss/src/apis/fastapi/sessions/models.py
  • api/oss/src/apis/fastapi/sessions/router.py
  • api/oss/src/core/sessions/commands/__init__.py
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/core/sessions/commands/interfaces.py
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/src/core/sessions/interactions/interfaces.py
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/core/sessions/streams/dtos.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • api/oss/src/core/sessions/streams/service.py
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/src/dbs/http/__init__.py
  • api/oss/src/dbs/http/sessions/__init__.py
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/dbs/postgres/sessions/commands/__init__.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/middlewares/auth.py
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/tasks/asyncio/sessions/records_worker.py
  • api/oss/src/tasks/asyncio/shared/consumer.py
  • api/oss/src/tasks/taskiq/triggers/worker.py
  • api/oss/src/utils/caching.py
  • api/oss/src/utils/crypting.py
  • api/oss/src/utils/env.py
  • api/oss/src/utils/exceptions.py
  • api/oss/src/utils/helpers.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_release_owner.py
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py
  • api/oss/tests/pytest/unit/sessions/test_runner_client_kill.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_feature_flag.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • api/oss/tests/pytest/unit/sessions/test_watch_publish.py
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_worker_lifecycle.py
  • api/oss/tests/pytest/unit/utils/test_caching.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/agent-workflows/documentation/adapters/agenta.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/addendum-always-active.md
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/api-design.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-admission.md
  • docs/design/session-control-and-live-events/slice-durable-cancel.md
  • docs/design/session-control-and-live-events/slice-records-ack.md
  • docs/design/session-control-and-live-events/spike-a-sandbox-cancel.md
  • docs/design/session-control-and-live-events/spike-b-durable-commands-design.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/docker-compose/ee/env.ee.dev.example
  • hosting/docker-compose/oss/env.oss.dev.example
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
  • sdks/python/oss/tests/pytest/unit/agents/adapters/test_vercel_stream_conformance.py
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • services/runner/src/engines/sandbox_agent/agent-mount.ts
  • services/runner/src/engines/sandbox_agent/cancel-turn.ts
  • services/runner/src/engines/sandbox_agent/credential-preflight.ts
  • services/runner/src/engines/sandbox_agent/engine.ts
  • services/runner/src/engines/sandbox_agent/environment-setup.ts
  • services/runner/src/engines/sandbox_agent/environment.ts
  • services/runner/src/engines/sandbox_agent/errors.ts
  • services/runner/src/engines/sandbox_agent/mount.ts
  • services/runner/src/engines/sandbox_agent/provider.ts
  • services/runner/src/engines/sandbox_agent/reap-exec.ts
  • services/runner/src/engines/sandbox_agent/reconstruct-history.ts
  • services/runner/src/engines/sandbox_agent/run-turn.ts
  • services/runner/src/engines/sandbox_agent/runtime-contracts.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • services/runner/src/environment/abortable-sandbox-provider.ts
  • services/runner/src/environment/acquire-abort.ts
  • services/runner/src/environment/harness-session-lifecycle.ts
  • services/runner/src/environment/mount-lifecycle.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/admission.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/src/sessions/applied-commands.ts
  • services/runner/src/sessions/control-channel.ts
  • services/runner/src/sessions/execution-registry.ts
  • services/runner/src/sessions/stop-signal.ts
  • services/runner/src/tracing/otel.ts
  • services/runner/tests/unit/acquire-abort.test.ts
  • services/runner/tests/unit/cancel-continuity.test.ts
  • services/runner/tests/unit/continuation.test.ts
  • services/runner/tests/unit/control-command-apply.test.ts
  • services/runner/tests/unit/credential-preflight.test.ts
  • services/runner/tests/unit/environment-units.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/tests/unit/reap-exec.test.ts
  • services/runner/tests/unit/sandbox-agent-mount.test.ts
  • services/runner/tests/unit/sandbox-agent-orchestration.test.ts
  • services/runner/tests/unit/sandbox-lifecycle.test.ts
  • services/runner/tests/unit/server.test.ts
  • services/runner/tests/unit/session-admission.test.ts
  • services/runner/tests/unit/session-alive-interrupt.test.ts
  • services/runner/tests/unit/session-keepalive-dispatch.test.ts
  • services/runner/tests/unit/session-ownership-release.test.ts
  • services/runner/tests/unit/session-pool.test.ts
  • services/runner/tests/unit/session-reconstruct-history.test.ts
  • services/runner/tests/unit/session-steer-mount-loss.test.ts
  • services/runner/tests/unit/teardown.test.ts
  • web/ee/package.json
  • web/mobile/package.json
  • web/mobile/src/features/chat/Composer.tsx
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/model/error.ts
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts
  • web/packages/agenta-chat/tests/unit/model/error.test.ts
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • web/packages/agenta-entities/src/session/core/schema.ts
  • web/packages/agenta-entities/src/session/index.ts
  • web/packages/agenta-entities/src/workflow/state/store.ts
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts
  • web/packages/agenta-entities/tests/unit/session-cancel-api.test.ts
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts
🚧 Files skipped from review as they are similar to previous changes (58)
  • docs/design/session-control-and-live-events/README.md
  • web/packages/agenta-entities/src/session/core/schema.ts
  • api/oss/src/middlewares/auth.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • hosting/docker-compose/oss/env.oss.dev.example
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • hosting/docker-compose/ee/env.ee.dev.example
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • web/packages/agenta-entities/src/session/index.ts
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • api/oss/src/core/sessions/interactions/interfaces.py
  • services/runner/src/sessions/stop-signal.ts
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • services/runner/src/engines/sandbox_agent/engine.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • web/packages/agenta-entities/tests/unit/session-cancel-api.test.ts
  • services/runner/src/tracing/otel.ts
  • api/oss/src/core/sessions/streams/dtos.py
  • services/runner/tests/unit/session-pool.test.ts
  • api/oss/src/apis/fastapi/sessions/models.py
  • services/runner/src/sessions/execution-registry.ts
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • services/runner/src/sessions/control-channel.ts
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • services/runner/src/server.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • services/runner/tests/unit/teardown.test.ts
  • services/runner/src/sessions/applied-commands.ts
  • api/oss/src/core/sessions/commands/interfaces.py
  • services/runner/tests/unit/control-command-apply.test.ts
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • api/entrypoints/routers.py

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.


📝 Summary

Summary by CodeRabbit

  • New Features

    • Added durable session Stop support with reliable delivery, idempotency, execution safeguards, and status reporting.
    • Stopped executions can preserve warm sessions when cancellation completes successfully.
    • Added session cancellation API support with optional execution matching and conflict responses.
    • Improved liveness polling based on session activity.
  • Bug Fixes

    • Prevented stale Stops from affecting newer executions.
    • Preserved unsent messages when a session is already busy.
    • Improved record delivery reliability and retry handling.
    • Persisted workflow build-kit preferences across reloads.
  • Documentation

    • Added design documentation for session control, cancellation, live events, and durable commands.

Walkthrough

The change adds durable Stop commands, runner-side cancellation and warm parking, single-turn admission, cancellation records, commit-aware record redelivery, adaptive liveness polling, client execution targeting, persisted build-kit state, and release-gate validation.

Changes

Session control and runner lifecycle

Layer / File(s) Summary
Durable Stop flow
api/oss/src/core/sessions/commands/*, api/oss/src/dbs/postgres/sessions/commands/*, api/oss/databases/postgres/migrations/..., api/oss/src/apis/fastapi/sessions/*, api/entrypoints/routers.py
Adds durable command contracts, PostgreSQL persistence, idempotent admission, direct runner delivery, outcome reporting, settlement guards, authentication, and feature-flagged legacy fallback.
Runner cancellation and warm parking
services/runner/src/server.ts, services/runner/src/sessions/*, services/runner/src/engines/sandbox_agent/*, services/runner/src/environment/*, services/runner/src/lifecycle/*, services/runner/patches/*
Adds execution registries, deduplicated Stop handling, harness settlement detection, cooperative abort labels, warm parking, stopped-session TTLs, acquisition cancellation, history verification, and Codex child reaping.
Single-turn admission and client handling
services/runner/src/sessions/admission.ts, services/runner/src/lifecycle/session-coordinator.ts, services/runner/src/protocol.ts, web/packages/agenta-chat/*, web/oss/src/components/AgentChatSlice/*, sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
Refuses concurrent turns without evicting the active environment, emits the admitted turn ID, restores refused message text, and forwards turn metadata to clients.
Records and session-state reliability
api/oss/src/tasks/asyncio/sessions/records_worker.py, api/oss/src/tasks/asyncio/shared/consumer.py, api/oss/src/core/sessions/interactions/*, api/oss/src/core/sessions/streams/*, api/ee/src/dbs/postgres/sessions/records/dao.py
Acknowledges record messages only after committed writes or deliberate drops, reclaims pending entries, isolates rejected records, records cancelled interactions, and fixes retention keying.
Client APIs, polling, and persisted UI state
web/packages/agenta-entities/src/session/*, web/mobile/src/features/sessions/*, web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts, web/packages/agenta-navigation/*, web/packages/agenta-entities/src/workflow/state/store.ts
Adds validated cancellation calls, shared liveness cadence, session-stop integration, and per-revision localStorage persistence for build-kit controls.
Validation and design support
.agents/skills/agent-release-gate/*, api/oss/tests/*, services/runner/tests/*, web/packages/*/tests/*, docs/design/session-control-and-live-events/*, hosting/docker-compose/*
Adds unit and integration coverage, mandatory session-control release cells, recorded-result validation, design documentation, and development Durable Stop settings.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟠 High · up to cd214

Merging can cancel the wrong active turn, lose deferred transcript records or rejected-message state, and expose command control across insufficiently scoped runner boundaries. These issues should be fixed before merge.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SessionControlRouter
  participant PostgreSQL
  participant Runner
  participant SandboxAgent
  Client->>SessionControlRouter: POST /sessions/{session_id}/cancel
  SessionControlRouter->>PostgreSQL: Store pending command
  SessionControlRouter->>Runner: POST /cancel
  Runner->>SandboxAgent: Send session/cancel
  SandboxAgent-->>Runner: Confirm or timeout
  Runner->>SessionControlRouter: Report outcome
  SessionControlRouter->>PostgreSQL: Settle command
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.15% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 372 functions across 50 files. (117 skipp… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the primary change: direct delivery of durable session Stop commands to the runner.
Description check ✅ Passed The description directly explains the durable Stop implementation, feature flag, API routes, runner delivery, settlement behavior, tests, evidence, and known limitations.
Full details: Docstring Coverage

Explanation

Docstring coverage is 27.15% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 372 functions across 50 files. (117 skipped: 38 unsupported, 79 over the file limit.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/session-durable-cancel

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mmabrouk mmabrouk changed the title [overnight] feat(sessions): durable Stop command with the direct-call adapter (package F) feat(sessions): deliver durable Stop directly to the runner Sep 3, 2026
@mmabrouk
mmabrouk changed the base branch from spike/session-cancel-warm to main September 4, 2026 07:04
mmabrouk added a commit that referenced this pull request Sep 4, 2026
…on id

PR #6503 already uses oss000000022 on the same parent. This file becomes oss000000025 so
both branches can merge; whichever lands second re-points down_revision to the new head.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGENT-GENERATED review, low weight. A read guide and the points a human should check; not an approval.

Read in this order

  1. api/oss/src/core/sessions/commands/service.py — admission, the three late-Stop guards, delivery, settlement.
  2. api/oss/databases/.../oss000000022_add_session_commands.py — the table, the partial unique index, the two session_streams columns.
  3. api/oss/src/dbs/postgres/sessions/commands/dao.py — every transition is one guarded compare-and-set.
  4. api/oss/src/apis/fastapi/sessions/router.py + middlewares/auth.py — the public Stop route and the runner-token outcome route.
  5. web/oss/.../useAgentChatSession.ts — the Stop button, now on the durable endpoint.

Top findings

  • One coherent change; the DAO compare-and-set tests run against real Postgres and are strong.
  • The rollback flag AGENTA_SESSIONS_DURABLE_STOP is NOT in this PR — the frontend switches to the new endpoint unconditionally and the route is always mounted. The gate arrives in #6501, so #6503 is safe only landed together with it. Confirm against the design's rollback contract.
  • Auth exemption /sessions/control/ collides with a session literally named control (see inline).
  • Migration is additive with a downgrade and chains cleanly on oss000000021; the outcome route fails closed with a constant-time compare.

Comment thread web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
Comment thread api/oss/src/middlewares/auth.py Outdated
Comment thread api/entrypoints/routers.py
Comment thread api/oss/src/apis/fastapi/sessions/router.py
Comment thread api/oss/src/core/sessions/commands/service.py
Comment thread api/oss/src/dbs/http/sessions/control_delivery_direct.py Outdated
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

📘 Docs preview

Status ✅ Ready
Preview https://pr-6503-agenta-docs-preview.mahmoud-637.workers.dev/docs
Inspect Actions run
Commit 3935e0cf4043a22a8c7c347bb3a6bbd32ce5c19e

This comment updates in place on every push.

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

  • Risky: services/runner/src/server.ts:753 - parked-session ownership ignores the project half of the pool key, so the same session ID in another project can make this runner accept a command it does not hold.
  • Risky: api/oss/src/core/sessions/commands/service.py:235 - an idempotency-key collision can return an old terminal command while the response names the newly running turn.
  • Missing tests: cross-project parked sessions with identical session IDs; reuse of one idempotency key after a later turn starts.

Reviewed at e4cbd64ac91a81f172c999667b9d6a3131b4467e. Advisory COMMENT review only.

Comment thread services/runner/src/server.ts Outdated
Comment thread api/oss/src/core/sessions/commands/service.py Outdated
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Status Destroyed (PR closed)

Updated at 2026-09-04T19:34:34.737Z

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/runner/patches/sandbox-agent@0.4.2.patch (1)

207-207: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Restore child termination on Windows.

When process.platform === "win32", use child.kill(signal) instead of process.kill(-child.pid, signal). The detached child can remain running when the process-group call throws and the empty catch discards the error.

🧹 Nitpick comments (3)
docs/design/session-control-and-live-events/slice-durable-cancel.md (1)

122-124: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the Fern-generated client for Stop.

Add the cancellation route to Fern, regenerate the sessions client, and replace the raw axios.post in cancelSessionExecution. Preserve the request fields and 409 handling. Update this paragraph to state that the Fern client is used.

api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py (1)

879-880: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert that the late claim is attempted.

_ReportsBeforeTheClaimCommits.deliver settles the row before returning accepted, after which SessionCommandsService._deliver calls _dao.claim_for_delivery. Line 880 repeats line 877, so the test can pass if that late claim call is removed. Assert that dao.claims contains this command and "runner-1"; keep the existing outcome assertion.

api/oss/tests/pytest/unit/sessions/test_session_cancel_feature_flag.py (1)

94-94: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Pin the durable response body, not only the status code.

Assert the JSON returned by SessionCancelResponse with the command ID and pending state, plus execution ID and stopping state. This test should detect future wire-contract changes.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 9f7a6b40-593b-4f4a-8d51-dc8df0bfeef9

📥 Commits

Reviewing files that changed from the base of the PR and between ded2cc3 and e4cbd64.

⛔ Files ignored due to path filters (1)
  • services/runner/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (81)
  • api/entrypoints/routers.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/apis/fastapi/sessions/models.py
  • api/oss/src/apis/fastapi/sessions/router.py
  • api/oss/src/core/sessions/commands/__init__.py
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/core/sessions/commands/interfaces.py
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/src/core/sessions/interactions/interfaces.py
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/core/sessions/streams/dtos.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • api/oss/src/core/sessions/streams/service.py
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/src/dbs/http/__init__.py
  • api/oss/src/dbs/http/sessions/__init__.py
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/dbs/postgres/sessions/commands/__init__.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/middlewares/auth.py
  • api/oss/src/utils/env.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_feature_flag.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/api-design.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-durable-cancel.md
  • docs/design/session-control-and-live-events/spike-a-sandbox-cancel.md
  • docs/design/session-control-and-live-events/spike-b-durable-commands-design.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/docker-compose/ee/env.ee.dev.example
  • hosting/docker-compose/oss/env.oss.dev.example
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • services/runner/src/engines/sandbox_agent/cancel-turn.ts
  • services/runner/src/engines/sandbox_agent/engine.ts
  • services/runner/src/engines/sandbox_agent/run-turn.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/applied-commands.ts
  • services/runner/src/sessions/control-channel.ts
  • services/runner/src/sessions/execution-registry.ts
  • services/runner/src/sessions/stop-signal.ts
  • services/runner/src/tracing/otel.ts
  • services/runner/tests/unit/control-command-apply.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/tests/unit/session-pool.test.ts
  • services/runner/tests/unit/teardown.test.ts
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • web/packages/agenta-entities/src/session/index.ts
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review.

Comment thread api/oss/src/apis/fastapi/sessions/router.py Outdated
Comment thread api/oss/src/core/sessions/interactions/service.py Outdated
Comment thread api/oss/src/core/sessions/streams/runner_client.py
Comment thread api/oss/src/core/sessions/streams/runner_client.py Outdated
Comment thread docs/design/session-control-and-live-events/api-design.md Outdated
Comment thread web/mobile/src/features/sessions/useActionableInteractions.ts Outdated
Comment thread web/mobile/src/features/sessions/useActionableInteractions.ts Outdated
Comment thread web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts Outdated
Comment thread web/packages/agenta-entities/src/session/api/api.ts Outdated
Comment thread web/packages/agenta-entities/src/session/api/api.ts Outdated
A user Stop reached the runner only as the absence of a Redis lock, noticed on
the next heartbeat up to 30 seconds later. Nothing recorded that a Stop had been
asked for, so a Stop against an unreachable runner was simply lost and no
execution ever reached a terminal outcome anyone could read.

Add session_commands: one row per durable request to change an execution. Two
columns that are never merged carry the two questions a caller actually asks.
state says where the COMMAND is (pending, claimed, applied, obsolete). outcome
says what happened to the EXECUTION (stopped, not_running,
superseded_by_newer_turn, failed, lost). A client drawing a Stop button reads the
execution; a client retrying safely reads the command id.

Every transition is one UPDATE ... WHERE <expected state> RETURNING *, decided by
scalar_one_or_none, the same compare-and-set transition_interaction already uses.
That is what stops two API replicas both winning a claim or both writing a
terminal outcome. Idempotency has two layers: the caller's Idempotency-Key on
(project_id, session_id, idempotency_key), and a collapse onto any open command
for the same target execution, which is what makes two Stops in a row correct
without asking the browser to send a key.

session_streams gains two columns. stopping_turn_id names the execution an
accepted Stop is waiting on, written in the same transaction as the command
insert. turn_started_at records when the row's current turn_id started, because
the stale-Stop guard has to compare a Stop's arrival time with the running
execution's start time and there was nowhere to read that: updated_at is the
heartbeat timestamp and moves every 30 seconds, runner-minted turn ids are uuid4
and carry no time, the Redis lock value is a bare turn id a Lua compare reads
whole, and the session_turns append is fire-and-forget so a running turn may have
no row. It is stamped only when the id actually changes, so the repeated
heartbeats that restamp the same id never move it.

Both columns backfill to NULL. A row written before this migration yields no
comparison and the guard does not fire, deliberately: a guard that refused every
Stop it could not verify would break the common case to protect a rare one.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
Keep the execution-versus-warm invariants at the affected call sites while moving each changed code comment back to one concise line.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
Align the API design, decisions, status, and handoff with the implemented direct control adapter. Mark runner-initiated long polling as deferred behind the same delivery port.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
@mmabrouk
mmabrouk force-pushed the feat/session-durable-cancel branch from 2251b4d to cd21450 Compare September 4, 2026 17:20
@mmabrouk
mmabrouk changed the base branch from main to feat/session-control September 4, 2026 17:20
@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 7d9ba61a-653e-4a63-b809-75d469ee8856

📥 Commits

Reviewing files that changed from the base of the PR and between 69db342 and cd21450.

⛔ Files ignored due to path filters (13)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/runner/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • services/uv.lock is excluded by !**/*.lock
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/CancelSessionExecutionRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionCancelRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionStream.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/index.ts is excluded by !**/generated/**
📒 Files selected for processing (172)
  • .agents/skills/agent-release-gate/SKILL.md
  • .agents/skills/agent-release-gate/resources/path_triggers.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • .agents/skills/agent-release-gate/resources/session_control.py
  • .agents/skills/agent-release-gate/resources/test_qa_product_concurrency.py
  • .agents/skills/agent-release-gate/resources/test_session_control.py
  • .all-contributorsrc
  • README.md
  • api/ee/src/dbs/postgres/sessions/records/dao.py
  • api/entrypoints/routers.py
  • api/entrypoints/worker_streams.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/apis/fastapi/evaluations/router.py
  • api/oss/src/apis/fastapi/sessions/models.py
  • api/oss/src/apis/fastapi/sessions/router.py
  • api/oss/src/core/sessions/commands/__init__.py
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/core/sessions/commands/interfaces.py
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/src/core/sessions/interactions/interfaces.py
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/core/sessions/streams/dtos.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • api/oss/src/core/sessions/streams/service.py
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/src/dbs/http/__init__.py
  • api/oss/src/dbs/http/sessions/__init__.py
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/dbs/postgres/sessions/commands/__init__.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/middlewares/auth.py
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/tasks/asyncio/sessions/records_worker.py
  • api/oss/src/tasks/asyncio/shared/consumer.py
  • api/oss/src/tasks/taskiq/triggers/worker.py
  • api/oss/src/utils/caching.py
  • api/oss/src/utils/crypting.py
  • api/oss/src/utils/env.py
  • api/oss/src/utils/exceptions.py
  • api/oss/src/utils/helpers.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_release_owner.py
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py
  • api/oss/tests/pytest/unit/sessions/test_runner_client_kill.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_feature_flag.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • api/oss/tests/pytest/unit/sessions/test_watch_publish.py
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_worker_lifecycle.py
  • api/oss/tests/pytest/unit/utils/test_caching.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/agent-workflows/documentation/adapters/agenta.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/addendum-always-active.md
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/api-design.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-admission.md
  • docs/design/session-control-and-live-events/slice-durable-cancel.md
  • docs/design/session-control-and-live-events/slice-records-ack.md
  • docs/design/session-control-and-live-events/spike-a-sandbox-cancel.md
  • docs/design/session-control-and-live-events/spike-b-durable-commands-design.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/docker-compose/ee/env.ee.dev.example
  • hosting/docker-compose/oss/env.oss.dev.example
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
  • sdks/python/oss/tests/pytest/unit/agents/adapters/test_vercel_stream_conformance.py
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • services/runner/src/engines/sandbox_agent/agent-mount.ts
  • services/runner/src/engines/sandbox_agent/cancel-turn.ts
  • services/runner/src/engines/sandbox_agent/credential-preflight.ts
  • services/runner/src/engines/sandbox_agent/engine.ts
  • services/runner/src/engines/sandbox_agent/environment-setup.ts
  • services/runner/src/engines/sandbox_agent/environment.ts
  • services/runner/src/engines/sandbox_agent/errors.ts
  • services/runner/src/engines/sandbox_agent/mount.ts
  • services/runner/src/engines/sandbox_agent/provider.ts
  • services/runner/src/engines/sandbox_agent/reap-exec.ts
  • services/runner/src/engines/sandbox_agent/reconstruct-history.ts
  • services/runner/src/engines/sandbox_agent/run-turn.ts
  • services/runner/src/engines/sandbox_agent/runtime-contracts.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • services/runner/src/environment/abortable-sandbox-provider.ts
  • services/runner/src/environment/acquire-abort.ts
  • services/runner/src/environment/harness-session-lifecycle.ts
  • services/runner/src/environment/mount-lifecycle.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/admission.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/src/sessions/applied-commands.ts
  • services/runner/src/sessions/control-channel.ts
  • services/runner/src/sessions/execution-registry.ts
  • services/runner/src/sessions/stop-signal.ts
  • services/runner/src/tracing/otel.ts
  • services/runner/tests/unit/acquire-abort.test.ts
  • services/runner/tests/unit/cancel-continuity.test.ts
  • services/runner/tests/unit/continuation.test.ts
  • services/runner/tests/unit/control-command-apply.test.ts
  • services/runner/tests/unit/credential-preflight.test.ts
  • services/runner/tests/unit/environment-units.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/tests/unit/reap-exec.test.ts
  • services/runner/tests/unit/sandbox-agent-mount.test.ts
  • services/runner/tests/unit/sandbox-agent-orchestration.test.ts
  • services/runner/tests/unit/sandbox-lifecycle.test.ts
  • services/runner/tests/unit/server.test.ts
  • services/runner/tests/unit/session-admission.test.ts
  • services/runner/tests/unit/session-alive-interrupt.test.ts
  • services/runner/tests/unit/session-keepalive-dispatch.test.ts
  • services/runner/tests/unit/session-ownership-release.test.ts
  • services/runner/tests/unit/session-pool.test.ts
  • services/runner/tests/unit/session-reconstruct-history.test.ts
  • services/runner/tests/unit/session-steer-mount-loss.test.ts
  • services/runner/tests/unit/teardown.test.ts
  • web/ee/package.json
  • web/mobile/package.json
  • web/mobile/src/features/chat/Composer.tsx
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/model/error.ts
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts
  • web/packages/agenta-chat/tests/unit/model/error.test.ts
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • web/packages/agenta-entities/src/session/core/schema.ts
  • web/packages/agenta-entities/src/session/index.ts
  • web/packages/agenta-entities/src/workflow/state/store.ts
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts
  • web/packages/agenta-entities/tests/unit/session-cancel-api.test.ts
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts
🚧 Files skipped from review as they are similar to previous changes (58)
  • docs/design/session-control-and-live-events/README.md
  • web/packages/agenta-entities/src/session/core/schema.ts
  • api/oss/src/middlewares/auth.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • hosting/docker-compose/oss/env.oss.dev.example
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • hosting/docker-compose/ee/env.ee.dev.example
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • web/packages/agenta-entities/src/session/index.ts
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • api/oss/src/core/sessions/interactions/interfaces.py
  • services/runner/src/sessions/stop-signal.ts
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • services/runner/src/engines/sandbox_agent/engine.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • web/packages/agenta-entities/tests/unit/session-cancel-api.test.ts
  • services/runner/src/tracing/otel.ts
  • api/oss/src/core/sessions/streams/dtos.py
  • services/runner/tests/unit/session-pool.test.ts
  • api/oss/src/apis/fastapi/sessions/models.py
  • services/runner/src/sessions/execution-registry.ts
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • services/runner/src/sessions/control-channel.ts
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • services/runner/src/server.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • services/runner/tests/unit/teardown.test.ts
  • services/runner/src/sessions/applied-commands.ts
  • api/oss/src/core/sessions/commands/interfaces.py
  • services/runner/tests/unit/control-command-apply.test.ts
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • api/entrypoints/routers.py

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 15


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 7d9ba61a-653e-4a63-b809-75d469ee8856

📥 Commits

Reviewing files that changed from the base of the PR and between 69db342 and cd21450.

⛔ Files ignored due to path filters (13)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/runner/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • services/uv.lock is excluded by !**/*.lock
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/Client.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/CancelSessionExecutionRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/SessionStreamCommandRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/resources/sessions/client/requests/index.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionCancelRequest.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionStream.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/SessionStreamCommandResponse.ts is excluded by !**/generated/**
  • web/packages/agenta-api-client/src/generated/api/types/index.ts is excluded by !**/generated/**
📒 Files selected for processing (172)
  • .agents/skills/agent-release-gate/SKILL.md
  • .agents/skills/agent-release-gate/resources/path_triggers.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • .agents/skills/agent-release-gate/resources/session_control.py
  • .agents/skills/agent-release-gate/resources/test_qa_product_concurrency.py
  • .agents/skills/agent-release-gate/resources/test_session_control.py
  • .all-contributorsrc
  • README.md
  • api/ee/src/dbs/postgres/sessions/records/dao.py
  • api/entrypoints/routers.py
  • api/entrypoints/worker_streams.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/apis/fastapi/evaluations/router.py
  • api/oss/src/apis/fastapi/sessions/models.py
  • api/oss/src/apis/fastapi/sessions/router.py
  • api/oss/src/core/sessions/commands/__init__.py
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/core/sessions/commands/interfaces.py
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/src/core/sessions/interactions/interfaces.py
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/core/sessions/streams/dtos.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • api/oss/src/core/sessions/streams/service.py
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/src/dbs/http/__init__.py
  • api/oss/src/dbs/http/sessions/__init__.py
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/dbs/postgres/sessions/commands/__init__.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/middlewares/auth.py
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/tasks/asyncio/sessions/records_worker.py
  • api/oss/src/tasks/asyncio/shared/consumer.py
  • api/oss/src/tasks/taskiq/triggers/worker.py
  • api/oss/src/utils/caching.py
  • api/oss/src/utils/crypting.py
  • api/oss/src/utils/env.py
  • api/oss/src/utils/exceptions.py
  • api/oss/src/utils/helpers.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_release_owner.py
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py
  • api/oss/tests/pytest/unit/sessions/test_runner_client_kill.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_feature_flag.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • api/oss/tests/pytest/unit/sessions/test_watch_publish.py
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_worker_lifecycle.py
  • api/oss/tests/pytest/unit/utils/test_caching.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/agent-workflows/documentation/adapters/agenta.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/addendum-always-active.md
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/api-design.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-admission.md
  • docs/design/session-control-and-live-events/slice-durable-cancel.md
  • docs/design/session-control-and-live-events/slice-records-ack.md
  • docs/design/session-control-and-live-events/spike-a-sandbox-cancel.md
  • docs/design/session-control-and-live-events/spike-b-durable-commands-design.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/docker-compose/ee/env.ee.dev.example
  • hosting/docker-compose/oss/env.oss.dev.example
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
  • sdks/python/oss/tests/pytest/unit/agents/adapters/test_vercel_stream_conformance.py
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • services/runner/src/engines/sandbox_agent/agent-mount.ts
  • services/runner/src/engines/sandbox_agent/cancel-turn.ts
  • services/runner/src/engines/sandbox_agent/credential-preflight.ts
  • services/runner/src/engines/sandbox_agent/engine.ts
  • services/runner/src/engines/sandbox_agent/environment-setup.ts
  • services/runner/src/engines/sandbox_agent/environment.ts
  • services/runner/src/engines/sandbox_agent/errors.ts
  • services/runner/src/engines/sandbox_agent/mount.ts
  • services/runner/src/engines/sandbox_agent/provider.ts
  • services/runner/src/engines/sandbox_agent/reap-exec.ts
  • services/runner/src/engines/sandbox_agent/reconstruct-history.ts
  • services/runner/src/engines/sandbox_agent/run-turn.ts
  • services/runner/src/engines/sandbox_agent/runtime-contracts.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • services/runner/src/environment/abortable-sandbox-provider.ts
  • services/runner/src/environment/acquire-abort.ts
  • services/runner/src/environment/harness-session-lifecycle.ts
  • services/runner/src/environment/mount-lifecycle.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/admission.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/src/sessions/applied-commands.ts
  • services/runner/src/sessions/control-channel.ts
  • services/runner/src/sessions/execution-registry.ts
  • services/runner/src/sessions/stop-signal.ts
  • services/runner/src/tracing/otel.ts
  • services/runner/tests/unit/acquire-abort.test.ts
  • services/runner/tests/unit/cancel-continuity.test.ts
  • services/runner/tests/unit/continuation.test.ts
  • services/runner/tests/unit/control-command-apply.test.ts
  • services/runner/tests/unit/credential-preflight.test.ts
  • services/runner/tests/unit/environment-units.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/tests/unit/reap-exec.test.ts
  • services/runner/tests/unit/sandbox-agent-mount.test.ts
  • services/runner/tests/unit/sandbox-agent-orchestration.test.ts
  • services/runner/tests/unit/sandbox-lifecycle.test.ts
  • services/runner/tests/unit/server.test.ts
  • services/runner/tests/unit/session-admission.test.ts
  • services/runner/tests/unit/session-alive-interrupt.test.ts
  • services/runner/tests/unit/session-keepalive-dispatch.test.ts
  • services/runner/tests/unit/session-ownership-release.test.ts
  • services/runner/tests/unit/session-pool.test.ts
  • services/runner/tests/unit/session-reconstruct-history.test.ts
  • services/runner/tests/unit/session-steer-mount-loss.test.ts
  • services/runner/tests/unit/teardown.test.ts
  • web/ee/package.json
  • web/mobile/package.json
  • web/mobile/src/features/chat/Composer.tsx
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/model/error.ts
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts
  • web/packages/agenta-chat/tests/unit/model/error.test.ts
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • web/packages/agenta-entities/src/session/core/schema.ts
  • web/packages/agenta-entities/src/session/index.ts
  • web/packages/agenta-entities/src/workflow/state/store.ts
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts
  • web/packages/agenta-entities/tests/unit/session-cancel-api.test.ts
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts
🚧 Files skipped from review as they are similar to previous changes (58)
  • docs/design/session-control-and-live-events/README.md
  • web/packages/agenta-entities/src/session/core/schema.ts
  • api/oss/src/middlewares/auth.py
  • api/oss/tests/pytest/unit/middlewares/test_auth_public_endpoints.py
  • services/runner/patches/sandbox-agent@0.4.2.patch
  • hosting/docker-compose/oss/env.oss.dev.example
  • web/packages/agenta-entities/src/session/api/api.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • api/oss/src/dbs/postgres/sessions/commands/dbas.py
  • web/packages/agenta-entities/tests/unit/session-liveness.test.ts
  • hosting/docker-compose/ee/env.ee.dev.example
  • api/oss/src/dbs/http/sessions/control_delivery_direct.py
  • api/oss/src/core/sessions/streams/runner_client.py
  • web/packages/agenta-entities/src/session/index.ts
  • api/oss/src/core/sessions/commands/types.py
  • api/oss/tests/pytest/unit/sessions/test_command_matrix_inputs_data.py
  • web/mobile/src/features/sessions/useLivenessPoll.ts
  • api/oss/src/core/sessions/interactions/interfaces.py
  • services/runner/src/sessions/stop-signal.ts
  • api/oss/tests/pytest/unit/sessions/test_watch_interactions_publish.py
  • services/runner/src/engines/sandbox_agent/engine.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
  • api/oss/src/core/sessions/interactions/service.py
  • api/oss/src/dbs/postgres/sessions/commands/mappings.py
  • api/oss/src/dbs/postgres/sessions/interactions/dao.py
  • web/packages/agenta-entities/tests/unit/session-cancel-api.test.ts
  • services/runner/src/tracing/otel.ts
  • api/oss/src/core/sessions/streams/dtos.py
  • services/runner/tests/unit/session-pool.test.ts
  • api/oss/src/apis/fastapi/sessions/models.py
  • services/runner/src/sessions/execution-registry.ts
  • api/oss/tests/pytest/unit/sessions/test_wp5_dao_fanout.py
  • api/oss/src/dbs/postgres/sessions/streams/dbes.py
  • services/runner/src/sessions/control-channel.ts
  • api/oss/tests/pytest/unit/sessions/test_interaction_cancel_records.py
  • services/runner/src/server.ts
  • web/packages/agenta-entities/src/session/core/liveness.ts
  • services/runner/tests/unit/teardown.test.ts
  • services/runner/src/sessions/applied-commands.ts
  • api/oss/src/core/sessions/commands/interfaces.py
  • services/runner/tests/unit/control-command-apply.test.ts
  • api/oss/src/core/sessions/commands/dtos.py
  • api/oss/src/dbs/postgres/sessions/streams/mappings.py
  • api/oss/src/dbs/postgres/sessions/commands/dbes.py
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • api/oss/src/core/sessions/commands/service.py
  • api/oss/tests/pytest/unit/sessions/test_session_commands_dao.py
  • web/packages/agenta-navigation/tests/unit/sidebarChildren.test.ts
  • services/runner/tests/unit/harness-cancel-park.test.ts
  • services/runner/src/engines/sandbox_agent/teardown.ts
  • api/oss/src/core/sessions/streams/types.py
  • api/oss/databases/postgres/migrations/core_oss/versions/oss000000022_add_session_commands.py
  • api/oss/src/dbs/postgres/sessions/commands/dao.py
  • api/oss/tests/pytest/unit/sessions/test_session_cancel_admission.py
  • web/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.ts
  • web/mobile/src/features/sessions/useActionableInteractions.ts
  • services/runner/src/engines/sandbox_agent/session-identity.ts
  • api/entrypoints/routers.py

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.

🛑 Comments failed to post (15)
.agents/skills/agent-release-gate/resources/path_triggers.py (1)

88-91: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Trigger session-control evidence for persistence and composition-root changes.

A release limited to api/oss/src/dbs/postgres/sessions/**, the related session-command migration, or session-control wiring in api/entrypoints/** does not require session_control.py. Those paths can break durable Stop persistence or delivery while the release gate remains green.

  • .agents/skills/agent-release-gate/resources/path_triggers.py#L88-L91: Add path rules for session persistence, relevant migrations, and session-control composition roots.
  • .agents/skills/agent-release-gate/SKILL.md#L195-L199: Document the same expanded mandatory-path scope.
📍 Affects 2 files
  • .agents/skills/agent-release-gate/resources/path_triggers.py#L88-L91 (this comment)
  • .agents/skills/agent-release-gate/SKILL.md#L195-L199
api/oss/src/apis/fastapi/sessions/router.py (1)

1983-1983: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject oversized idempotency keys. cancel_session_execution truncates the normalized key before request_cancel. The DAO uses that value for the unique command lookup, so two distinct keys with the same first 255 characters can replay the first command after a later execution starts. If the normalized key exceeds 255 characters, return HTTP 422 instead of truncating it.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        idempotency_key = request.headers.get("Idempotency-Key")
        if idempotency_key is not None:
            idempotency_key = idempotency_key.strip()
            if len(idempotency_key) > _MAX_IDEMPOTENCY_KEY_CHARACTERS:
                raise HTTPException(
                    status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                    detail="Idempotency-Key is too long.",
                )
            idempotency_key = idempotency_key or None
api/oss/src/core/sessions/streams/service.py (1)

212-215: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make expected-turn cancellation atomic.

A new turn can replace the locks after the earlier owner check. This path then tombstones and clears that new turn. Use an atomic compare-and-delete or fencing operation that verifies expected_turn_id at the lock mutation point.

api/oss/src/tasks/asyncio/sessions/records_worker.py (1)

243-248: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🔎 Supported by static analysis

🤖 get_repo_knowledge executed:

get_repo_knowledge Agenta-AI/agenta /tmp/coderabbit-repo-knowledge/agenta-ai-agenta-4b53879a/learnings /tmp/coderabbit-repo-knowledge/agenta-ai-agenta-4b53879a/conventions

Length of output: 12646


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- worker outline ---'
ast-grep outline api/oss/src/tasks/asyncio/sessions/records_worker.py

printf '%s\n' '--- worker focused source ---'
sed -n '1,125p' api/oss/src/tasks/asyncio/sessions/records_worker.py
sed -n '150,390p' api/oss/src/tasks/asyncio/sessions/records_worker.py

printf '%s\n' '--- directly bound reclaim symbols and callers ---'
rg -n -C 5 'reclaim_batch|drop_expired|max_deliveries|_last_commit_at|process_batch|quota|entitlement|org_deferred' api/oss/src/tasks/asyncio api/oss/src -g '*.py'

Repository: Agenta-AI/agenta

Length of output: 50373


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- consumer size and outline ---'
wc -l api/oss/src/tasks/asyncio/shared/consumer.py
ast-grep outline api/oss/src/tasks/asyncio/shared/consumer.py

printf '%s\n' '--- consumer implementation ---'
sed -n '1,420p' api/oss/src/tasks/asyncio/shared/consumer.py

printf '%s\n' '--- focused tests and configuration ---'
rg -n -C 6 'reclaim_batch|drop_expired|mark_committed|last_commit|max_deliveries|reclaim_pending' api/oss/tests api/oss/src/tasks/asyncio/shared api/oss/src/utils/env.py -g '*.py'

Repository: Agenta-AI/agenta

Length of output: 44429


Exclude quota-deferred entries from StreamConsumer’s delivery budget.

When check_entitlements fails, RecordsWorker.process_batch leaves the entry pending. An unrelated successful append calls mark_committed(), so reclaim_batch can treat the path as healthy and drop_expired can acknowledge and delete the deferred entry after max_deliveries. Track deferred entries or retry the quota check before expiration.

Add a regression with one successful project and one project with repeated entitlement failures. The deferred entry must remain pending beyond max_deliveries.

api/oss/src/utils/env.py (1)

528-532: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject non-positive record recovery settings. AGENTA_RECORDS_RECLAIM_IDLE_MS=0 makes StreamConsumer claim pending entries on every loop. Negative idle values make Redis reclaim calls invalid. AGENTA_RECORDS_MAX_DELIVERIES<=0 can make a healthy consumer ACK/delete a pending record before its next retry. Use _parse_optional_positive_int_env for both settings.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    reclaim_idle_ms: int = (
        _parse_optional_positive_int_env("AGENTA_RECORDS_RECLAIM_IDLE_MS")
        or 30_000
    )

    # Deliveries after which a record message is dropped instead of retried forever. A message
    # Postgres never accepts would otherwise hold every later message in the group.
    max_deliveries: int = (
        _parse_optional_positive_int_env("AGENTA_RECORDS_MAX_DELIVERIES") or 5
    )
docs/design/session-control-and-live-events/spike-b-durable-commands-design.md (1)

519-521: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
file='docs/design/session-control-and-live-events/spike-b-durable-commands-design.md'
printf '%s\n' '--- relevant identifiers and authorization terms ---'
rg -n -C 4 'AGENTA_RUNNER_TOKEN|replica_id|sessions|lease|owner|claim|settle|consume|authorization|authenticate|project scope' "$file"
printf '%s\n' '--- target context ---'
sed -n '470,545p' "$file"

Repository: Agenta-AI/agenta

Length of output: 50374


🤖 get_repo_knowledge executed:

get_repo_knowledge Agenta-AI/agenta /tmp/coderabbit-repo-knowledge/agenta-ai-agenta-4b53879a/learnings /tmp/coderabbit-repo-knowledge/agenta-ai-agenta-4b53879a/conventions

Length of output: 23964


🏁 Script executed:

#!/bin/bash
set -eu
file='docs/design/session-control-and-live-events/spike-b-durable-commands-design.md'
printf '%s\n' '--- authentication and claim contract ---'
sed -n '494,545p' "$file"
printf '%s\n' '--- runner contract and ownership-related terms ---'
sed -n '637,670p' "$file"
sed -n '918,1015p' "$file"
printf '%s\n' '--- bounded ownership checks ---'
rg -n -C 3 'not_held|held_sessions|owns|owner|lease|replica_id|runner token|AGENTA_RUNNER_TOKEN|server-side|authorize|authorization' "$file" | tail -n 180

Repository: Agenta-AI/agenta

Length of output: 21726


Authorization Bypass (CWE-639): Authorization Bypass Through User-Controlled Key (IDOR)

Reachability: Internal · Exploitability: Difficult

Bind declared sessions to the authenticated runner.

The shared AGENTA_RUNNER_TOKEN does not bind a caller to its sessions or replica_id. The claim query and settlement guard trust both caller-supplied values, so a token holder can claim commands for another project and settle them. Require a server-side runner lease or owner check for every declared session, or use credentials scoped to the allowed sessions.

services/runner/src/environment/mount-lifecycle.ts (1)

211-211: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -e
file="services/runner/src/environment/mount-lifecycle.ts"
wc -l "$file"
sed -n '1,290p' "$file"
printf '\n--- directly bound symbols ---\n'
rg -n --glob '*.ts' 'function (throwIfAcquireAborted|rethrowIfInvariant)|const (throwIfAcquireAborted|rethrowIfInvariant)|throwIfAcquireAborted|rethrowIfInvariant|commitLocalMount|mountStorage|AcquireAbortedError' services/runner/src

Repository: Agenta-AI/agenta

Length of output: 22542


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- acquire-abort.ts ---'
cat -n services/runner/src/environment/acquire-abort.ts
printf '%s\n' '--- acquire-context.ts: commit and mount state ---'
sed -n '90,155p' services/runner/src/environment/acquire-context.ts
sed -n '235,305p' services/runner/src/environment/acquire-context.ts
printf '%s\n' '--- context implementation: commit and cleanup-related methods ---'
sed -n '90,175p' services/runner/src/environment/acquire-context-impl.ts
printf '%s\n' '--- mountStorage success/abort path ---'
sed -n '300,455p' services/runner/src/engines/sandbox_agent/mount.ts
printf '%s\n' '--- callers and teardown references ---'
rg -n -C 8 --glob '*.ts' 'mountLocalDurableCwd|mountLocalAgentCwd|mountedCwd|agentMountedPath|unmountStorage\\(' services/runner/src/environment services/runner/src/engines/sandbox_agent/environment.ts

Repository: Agenta-AI/agenta

Length of output: 19676


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- mount lifecycle callers and remaining functions ---'
sed -n '290,391p' services/runner/src/environment/mount-lifecycle.ts
printf '%s\n' '--- environment acquisition and teardown around local mounts ---'
sed -n '410,490p' services/runner/src/engines/sandbox_agent/environment.ts
sed -n '520,590p' services/runner/src/engines/sandbox_agent/environment.ts
sed -n '740,785p' services/runner/src/engines/sandbox_agent/environment.ts
printf '%s\n' '--- all direct call sites ---'
rg -n -C 6 --glob '*.ts' 'mountLocalDurableCwd|mountLocalAgentCwd' services/runner/src

Repository: Agenta-AI/agenta

Length of output: 34364


Commit each successful local mount before propagating acquisition aborts. Both helpers can receive true from mountStorage, then throw before ctx.commitLocalMount; teardown therefore has no mountedCwd or agentMountedPath to unmount. Commit immediately after success, then propagate AcquireAbortedError. In mountLocalAgentCwd, rethrowIfInvariant does not rethrow AcquireAbortedError, so the catch logs it as a normal mount failure and returns false.

📍 Affects 1 file
  • services/runner/src/environment/mount-lifecycle.ts#L211-L211 (this comment)
  • services/runner/src/environment/mount-lifecycle.ts#L247-L255
services/runner/tests/unit/sandbox-agent-orchestration.test.ts (1)

2637-2640: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Assert that the paused execution remains registered

findExecution(... )?.settled is undefined both when the entry is present and unsettled and when the entry is absent. The test can therefore pass after the registry entry is removed, leaving the live-turn lookup and cancellation invariant untested.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const execution = findExecution(
      "11111111-1111-4111-8111-111111111111",
      sessionId,
    );
    assert.ok(execution, "the paused turn stays registered");
    assert.equal(execution.settled, undefined);
services/runner/tests/unit/session-alive-interrupt.test.ts (1)

178-187: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Exercise the interval heartbeat and assert onInterrupted. startAliveWatchdog starts its 30-second setInterval only after the first beat. flushMicrotasks() waits 0 ms, and this test does not provide an onInterrupted callback. Therefore it never observes the later interruption, so a broken production path can still pass. Use fake timers to advance one interval, then assert onInterrupted fires while watchdog.admitted remains true.

services/runner/tests/unit/session-steer-mount-loss.test.ts (1)

457-459: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match the fake teardown markers in the assertion. makeHost().teardown emits only unmount and rmSync, so includes("teardown") is always false. This test otherwise allows a refusal regression that acquires and tears down a rival environment to pass because it checks only the original environment's destroyed count.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    assert.ok(
      !host.trace.some(
        (line) => line.includes("unmount") || line.includes("rmSync"),
      ),
      `a teardown ran during the refusal: ${host.trace.join(" | ")}`,
web/mobile/src/features/chat/Composer.tsx (1)

52-53: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Reduce the new in-code comments.

Each listed block exceeds one short line. Replace it with one brief reason-only comment, or remove it when the code is self-explanatory.

  • web/mobile/src/features/chat/Composer.tsx#L52-L53: reduce the placeholder comment to one short line.
  • web/mobile/src/features/chat/LiveConversation.tsx#L150-L151: reduce the pending-task comment to one short line.
  • web/mobile/src/features/chat/LiveConversation.tsx#L307-L311: remove or reduce the JSX comment to one short line.
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx#L430-L437: reduce the refusal-recovery comment to one short line.
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx#L162-L167: reduce the error-state comment to one short line.

As per coding guidelines, “Hard rule. At most ONE short line per comment.”

📍 Affects 4 files
  • web/mobile/src/features/chat/Composer.tsx#L52-L53 (this comment)
  • web/mobile/src/features/chat/LiveConversation.tsx#L150-L151
  • web/mobile/src/features/chat/LiveConversation.tsx#L307-L311
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx#L430-L437
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx#L162-L167

Source: Coding guidelines

web/oss/src/components/AgentChatSlice/AgentConversation.tsx (1)

440-442: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore consumed attachments on session-busy refusal.

finishSubmit calls attachments.clearAttachments(consumedUids) immediately after submit. The queue retains fileParts, but this effect restores only sent.text, so the staged files are removed and no other path restores them. Retain the consumed staged entries and pass them to attachments.restoreAttachments before the retry.

web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts (2)

86-97: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Reduce new code comments to one short line each.

The web guideline has a hard one-short-line limit per comment. Move detailed rationale to documentation or encode it in focused tests.

  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts#L86-L97: replace the long recovery rationale with one short comment.
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts#L212-L213: replace the two-line recovery comment with one short comment.
  • web/packages/agenta-chat/src/model/error.ts#L49-L59: replace the admission-contract block with one short comment.
  • web/packages/agenta-chat/src/model/error.ts#L65-L72: replace the matching rationale block with one short comment.
  • web/packages/agenta-chat/src/model/error.ts#L76-L78: remove the parity-history comment or reduce it to one short line.
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts#L367-L371: reduce the scenario explanation to one short line.
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts#L390-L391: reduce the queue-state explanation to one short line.
  • web/packages/agenta-chat/tests/unit/model/error.test.ts#L87-L90: reduce the runner-path explanation to one short line.
📍 Affects 4 files
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts#L86-L97 (this comment)
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts#L212-L213
  • web/packages/agenta-chat/src/model/error.ts#L49-L59
  • web/packages/agenta-chat/src/model/error.ts#L65-L72
  • web/packages/agenta-chat/src/model/error.ts#L76-L78
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts#L367-L371
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts#L390-L391
  • web/packages/agenta-chat/tests/unit/model/error.test.ts#L87-L90

Source: Coding guidelines


214-214: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -eu
file='web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts'
printf '%s\n' '--- focused source ---'
sed -n '1,260p' "$file"
printf '%s\n' '--- bound symbols and callers ---'
rg -n -C 3 'lastSentRef|takeLastSent|refus|release|send' "$file" web/packages/agenta-chat/src
printf '%s\n' '--- focused diff ---'
git diff --unified=30 -- "$file"

Repository: Agenta-AI/agenta

Length of output: 50373


🤖 get_repo_knowledge executed:

get_repo_knowledge Agenta-AI/agenta /tmp/coderabbit-repo-knowledge/agenta-ai-agenta-4b53879a/learnings

Length of output: 4671


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- hook consumers ---'
rg -l 'useAgentChatQueue|takeLastSent' web --glob '*.ts' --glob '*.tsx' | sort
printf '%s\n' '--- exact consumer context ---'
rg -n -C 12 'useAgentChatQueue|takeLastSent' web/packages web/apps --glob '*.ts' --glob '*.tsx'
printf '%s\n' '--- refusal classification and handlers ---'
rg -n -C 12 'SESSION_TURN_IN_USE|isSessionTurnInUse|takeLastSent|sendQueued|onError' web/packages/agenta-chat web/apps --glob '*.ts' --glob '*.tsx'

Repository: Agenta-AI/agenta

Length of output: 31616


🏁 Script executed:

#!/bin/bash
set -eu
file='web/packages/agenta-chat/src/hooks/useAgentConversation.ts'
printf '%s\n' '--- hook outline ---'
ast-grep outline "$file"
printf '%s\n' '--- queue integration ---'
sed -n '100,190p' "$file"
sed -n '450,570p' "$file"
printf '%s\n' '--- all host reclaim/error references ---'
rg -n -C 10 'takeLastSent|sendQueued|isSessionTurnInUse|SESSION_TURN_IN_USE|onError|sendMessage' web/packages/agenta-chat/src/hooks/useAgentConversation.ts web/oss/src/components/AgentChatSlice/AgentConversation.tsx

Repository: Agenta-AI/agenta

Length of output: 38981


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- OSS refusal effect and surrounding hook order ---'
sed -n '330,455p' web/oss/src/components/AgentChatSlice/AgentConversation.tsx
printf '%s\n' '--- release predicate binding ---'
rg -n -l 'canReleaseQueuedMessage' web/packages web/oss
rg -n -C 18 'canReleaseQueuedMessage' web/packages/agenta-playground web/packages/agenta-* web/oss 2>/dev/null | head -240
printf '%s\n' '--- package test setup and relevant release tests ---'
sed -n '360,425p' web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts

Repository: Agenta-AI/agenta

Length of output: 34540


Protect refusal recovery before releasing the queue head.

When a refusal exposes status === "error" with no pending HITL interaction, the queue can release B. Its effect stores B in the single-slot lastSentRef before the OSS refusal effect calls takeLastSent, so A can be lost. Preserve recovery by send identity or reclaim A before releasing B.

web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts (1)

1-6: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reduce these comments to one short line each.

  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts#L1-L6: replace the reload explanation with one short comment.
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts#L10-L12: replace the storage-stub explanation with one short comment.
  • web/packages/agenta-entities/src/workflow/state/store.ts#L1469-L1473: replace the persistence overview with one short comment.
  • web/packages/agenta-entities/src/workflow/state/store.ts#L1481-L1486: replace the normalization overview with one short comment.

As per coding guidelines: “Hard rule. At most ONE short line per comment.”

📍 Affects 2 files
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts#L1-L6 (this comment)
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts#L10-L12
  • web/packages/agenta-entities/src/workflow/state/store.ts#L1469-L1473
  • web/packages/agenta-entities/src/workflow/state/store.ts#L1481-L1486

Source: Coding guidelines

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-generated Codex review, low weight.

Verdict: CHANGES NEEDED

The rebase keeps the #6496 warm-Stop/Codex-reap work and the #6500 admission checks, but their integration with durable Stop leaves two release-blocking races. I also found one retry-contract defect and confirmed the flag-off desktop response still fails its client schema.

The flag-off transport itself is preserved: desktop reaches the legacy API service through /cancel, mobile continues to use the legacy stream command, and the runner receives the heartbeat-carried interrupt. The remaining client-side issue is that desktop waits for fetchSessionStream before aborting its local stream, so a slow read delays both local feedback and either Stop request.

No focused test was run; the failures follow from the current control flow, and the existing suites are green but do not compose registry replacement with asynchronous admission or abort a turn after PAUSED has won the prompt race.

Comment thread services/runner/src/server.ts Outdated
Comment thread services/runner/src/engines/sandbox_agent/run-turn.ts
Comment thread api/oss/src/core/sessions/commands/service.py
Comment thread web/packages/agenta-entities/src/session/api/api.ts
Register session executions only after asynchronous admission succeeds. Cover a refused second turn while Stop cancels the admitted turn.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
Re-check labelled Stop after paused teardown and close the registry race before terminal reporting. Clear parked approval state when the turn converts to cancellation.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
Resolve exact retry keys before consulting current execution state and reject keys reused with a different expected execution. Cover replay after a later turn starts.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
Accept the flag-off session command payload alongside the durable cancel response and normalize it without logging a schema error. Cover the API's exact legacy body.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
Start the session-stream snapshot and local abort in the same tick, then cancel the captured execution when the read completes. Cover the unresolved-read ordering.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk
Keep the fake cancel method behind a narrow structural view while returning the original SandboxAgent type. This lets the pause teardown regression participate in strict typechecking.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-generated Codex review, low weight.

CHANGES NEEDED

The post-admission registry fix, pause-teardown cancellation, pre-guard idempotency replay, and legacy flag-off parsing all satisfy the requested scenarios and have the right regression coverage. The P3 change also aborts the local stream in the same tick. However, that timing change reopens the wrong-execution race that the preceding target-capture fix closed: local Stop now unlocks queued/new sends before the asynchronous stream read has actually pinned turn A. I left one P1 inline.

Focused validation passed: nice -n 19 pnpm exec vitest run tests/unit/sandbox-agent-orchestration.test.ts -t "converts a Stop during pause teardown" --maxWorkers=3 (1 passed, 75 skipped). git diff --check cd21450f7e..HEAD also passed. No other regression was found in the six-commit fix range.

Comment thread web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts Outdated
Abort the local stream immediately while holding queued sends and regenerations until the session snapshot has pinned the stopped execution. Release new work as soon as the snapshot resolves so the durable cancel keeps targeting the turn the user saw.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-generated Codex review, low weight.

CHANGES NEEDED

Within one mount, Stop still aborts locally in the same tick; queued/new sends and regenerations wait for the snapshot, and the regression proves an attempted B admission stays held until cancellation is pinned to A. However, the gate is mount-local while the desktop session Chat and queue survive remounts, so the original wrong-turn race remains across a route/pane remount. I left one P1 inline.

Focused validation passed: nice -n 19 pnpm exec vitest run src/components/AgentChatSlice/assets/stopWhileResolvingExecution.test.ts --maxWorkers=3 (2 tests). No other regression was found in git diff 00fae4b739..HEAD.

Comment thread web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts Outdated
Remember the admitted turn id outside the hook mount and copy it into expected_execution_id before aborting the local stream. New sends can proceed immediately without changing an in-flight Stop's target, including across remounts.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-generated Codex review, low weight.

CHANGES NEEDED

The new target is mount-independent once captured, and Stop still aborts locally in the same tick. The B-admission and remount regressions both pass and prove a captured request still names A. One earlier startup race remains, and it also affects the flag-off legacy fence; I left one P1 inline.

Focused validation passed: nice -n 19 pnpm exec vitest run src/components/AgentChatSlice/assets/stopWhileResolvingExecution.test.ts --maxWorkers=3 (3 tests).

Comment thread web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts
Stop turn-id recovery at the latest user-message boundary so starting a new turn cannot restore the previous execution id before the new metadata arrives. Cover pre-metadata Stop with session-scoped cancellation and no stale expected id.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-generated Codex review, low weight.

CHANGES NEEDED

The four focused Stop regressions pass, and manual send, queued send, regenerate, and assistant rewind all enter the empty-id window correctly. The remaining P1 is that an unfenced cancel is not running-only in either server mode; the flag-off route is therefore behaviorally affected by this change.

Comment thread web/packages/agenta-chat/src/assets/agentTurn.ts
An unfenced Stop could fall back to a parked or recently finished alive owner while a newer turn was still entering admission. That could tombstone the stale turn without stopping the new one.

Resolve durable unfenced cancels only from the running owner. The legacy path now uses owner-checked releases for that same running-only target and performs no row or lifecycle writes when no turn is running. Named cancels retain the parked alive fallback.

Claude-Session: https://claude.ai/code/session_0164kzT6ttwpBtzvcDC6YzYk

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent-generated Codex review, low weight.

SHIP

No findings in d4c4e43..3935e0c. Both durable and flag-off legacy paths now make no-ID Stop running-only: before B owns running they leave parked A untouched and return an idle/no-op shape; once B runs they target B. Named Stops retain the alive-owner fallback, so stopping a parked approval remains reachable. The client normalizes both no-op forms to idle, not stopping. The earlier five fixes remain intact.

Focused legacy matrix: 10 passed.

@mmabrouk
mmabrouk merged commit 3f18f74 into feat/session-control Sep 4, 2026
67 of 71 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changes requested lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant