You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs/planning/TARGET_ARCHITECTURE.md Open Question 7 — "Does human-interactive chat belong in the queue at all?" — is still marked "Under consideration, not decided." The doc instructs: "Decide before the #946 pilot, which routes chat_with_agent — an interactive kind — through the queue first."
#946 shipped. The decision is overdue, and it is now being made implicitly by code.
Why this needs closing now
PR #1982 (#1766 soak prep) makes a pull pilot's dispatch queue-only for autonomous triggers while excluding interactive ones — human chat and Session-tab turns keep today's synchronous push path and today's Redis session lock. That is an implementation of Open Question 7's own candidate answer (the "scope cut" rather than added machinery), and it is load-bearing: without it, one FIFO ordered by queued_at parks a human turn behind N batch tasks until the held connection times out, and N competing workers can claim two turns of one session concurrently — the concurrent --resume on a single JSONL that the session lock exists to prevent.
So the answer is now encoded in working code that ships to production, while the doc still says undecided. That gap is the problem:
Nobody reviewing TARGET_ARCHITECTURE.md can tell that the boundary is already real.
The trigger carve-out in services/pull_pilot.py::pull_owns_dispatch looks like a local implementation detail; it is actually an architectural commitment.
Edge adapter — the WebSocket or a ?wait=true call holds open, enqueues, forwards the reply on the completion event. Synchronous UX, async internals, held connection times out. Consistent with Principle Feature/vector log retention #3; but carries the starvation + per-session-serialization problems above, unaddressed.
Scope cut — the durable queue carries autonomous traffic only (schedules, webhooks, agent-to-agent, loops, channel messages); human chat/session turns keep the direct synchronous path and the session lock. Concurrency becomes one physical budget of N per agent: interactive turns take a slot on arrival, workers pull batch work only when slots are spare, optionally reserving one slot so long batch turns can't lock chat out. The doc leans this way; fix(pull): make the pilot flag a true either/or + soak measurement set (#1766) #1982 implements it.
Acceptance Criteria
A decision is recorded in TARGET_ARCHITECTURE.md — Open Question 7 resolved, not merely annotated
Note the replica interaction the doc flags: under replica_count > 1, session JSONLs are single-container state, so sessions need affinity or shared storage regardless of which answer wins (open question 5 / Replica groups: horizontal scaling for single agents #927).
Summary
docs/planning/TARGET_ARCHITECTURE.mdOpen Question 7 — "Does human-interactive chat belong in the queue at all?" — is still marked "Under consideration, not decided." The doc instructs: "Decide before the #946 pilot, which routeschat_with_agent— an interactivekind— through the queue first."#946 shipped. The decision is overdue, and it is now being made implicitly by code.
Why this needs closing now
PR #1982 (#1766 soak prep) makes a pull pilot's dispatch queue-only for autonomous triggers while excluding interactive ones — human chat and Session-tab turns keep today's synchronous push path and today's Redis session lock. That is an implementation of Open Question 7's own candidate answer (the "scope cut" rather than added machinery), and it is load-bearing: without it, one FIFO ordered by
queued_atparks a human turn behind N batch tasks until the held connection times out, and N competing workers can claim two turns of one session concurrently — the concurrent--resumeon a single JSONL that the session lock exists to prevent.So the answer is now encoded in working code that ships to production, while the doc still says undecided. That gap is the problem:
TARGET_ARCHITECTURE.mdcan tell that the boundary is already real.services/pull_pilot.py::pull_owns_dispatchlooks like a local implementation detail; it is actually an architectural commitment.The two candidates (verbatim from the doc)
?wait=truecall holds open, enqueues, forwards the reply on the completion event. Synchronous UX, async internals, held connection times out. Consistent with Principle Feature/vector log retention #3; but carries the starvation + per-session-serialization problems above, unaddressed.Acceptance Criteria
TARGET_ARCHITECTURE.md— Open Question 7 resolved, not merely annotatedpull_owns_dispatch's docstring rather than that docstring being the only place it existsTechnical Notes
docs/planning/TARGET_ARCHITECTURE.mdOpen Question 7 (+ §Async-First Communication, which assumes the edge adapter).src/backend/services/pull_pilot.py::pull_owns_dispatch,capacity_manager.acquire.replica_count > 1, session JSONLs are single-container state, so sessions need affinity or shared storage regardless of which answer wins (open question 5 / Replica groups: horizontal scaling for single agents #927).