Repository navigation
Gateway fixes (#134889), package 10: the gateway process, clients that fall behind, credentials and settings, Desktop session lists and history, and messaging order #140719
Description
Part of #134889, the post-merge fixes for the unified gateway (#106742). This package collects 41 open findings in 5 lanes, most of them reported on Oct 17 after package 9 opened. None of them is in another package, none touches work another open package is changing, and none needs a maintainer decision. It's written to run unattended. Each lane is one kind of fix in one part of the code, so the lanes can run in parallel and sub-agents can fan out inside each lane. Start with GW-17 in lane 1 (bot messages acknowledged and lost) and RT-43 in lane 4 (a conversation stuck for good).
Sibling packages: #139158 (package 1, classic CLI) · #139160 (package 2, session creation, model picks and credentials) · #139161 (package 3, Ink TUI and Desktop) · #139162 (package 4, bots, cron and Kanban; closed, done) · #139523 (package 5, plugins and config the gateway reads once; closed, done) · #139574 (package 6, gateway, TUI and Desktop startup; closed, done) · #140138 (package 7, ACP, session writes and resume, bots, and Desktop capabilities; closed, done) · #140208 (package 8, deleted and older sessions, silent failures, commands, profile isolation and Desktop display; closed, done) · #140337 (package 9, detach and lost connections, Ink and Desktop leftovers, classic CLI leftovers, Windows, and new regressions; closed, done).
Direction: follow #106742
Every fix in this package must honor the vision and direction of the one-gateway PR, #106742 (feat/unified-gateway-runtime, merged to main on Oct 14). Read its description before starting, and put this section in the brief of every sub-agent you spawn.
- One gateway owns every local session: one FIFO, one durable queue, one writer. Fix the gateway path. Don't bring back a client-side agent, a local fallback, or a second writer to
state.db. - Clients only read and submit. A missing capability gets a gateway handler or a named refusal, not client-side state.
- Keep the contract: queued admissions survive an owner restart and run FIFO exactly once; a started admission that loses its owner becomes interrupted and is never replayed automatically; a retry reuses the original admission identity and payload.
- Profile, provider, generation and revision boundaries hold on every transport.
- Design calls are yours to make. Pick the option that best fits this design, and write the choice and the reason in the PR body. Stop and ask on Tracking: one gateway owns every local session (#106742) — post-merge fixes #134889 only when every option would break one of the rules above.
Working rules
- Branch from current
main. 🟡 rows haven't been reproduced: reproduce onmainfirst. A row that doesn't reproduce gets no commit; put the evidence (file:line, the probe test) in the lane's PR body and say so on Tracking: one gateway owns every local session (#106742) — post-merge fixes #134889. - Written for unattended runs: don't wait for answers. When a row leaves a choice open, decide by the Direction section above and record why in the PR body. If a row turns out to need a maintainer decision, or to change code another open package is changing, skip it and say so on Tracking: one gateway owns every local session (#106742) — post-merge fixes #134889 instead of guessing.
- Rows marked "not triaged yet" (PLG-13, KB-7, RT-45) or "suspected" / "probable" (CLI-38, RT-38) need the cause confirmed first. Write the probe, and fix only what it shows.
- Lanes touch different code, so they can run in parallel in separate worktrees. Open one PR per lane (split a lane if it grows), each with a failing test first.
- Sub-agents: one per row works, up to ten at once. Rows in the same lane share files, so tell each sub-agent which function or clause it owns, then assemble the lane's commits on one branch.
- Name the row ID in each PR (
Refs #134889 (GW-17)) and reference this issue.Fixesis fine for a row's own bug report (e.g.Fixes #140564), never for Tracking: one gateway owns every local session (#106742) — post-merge fixes #134889. - An open PR from an outside contributor doesn't cover a row. Every outside PR listed below allows maintainer edits. Review it. If it's right, finish it on the contributor's branch, or salvage it: cherry-pick their commit unchanged (
git cherry-pick -x) so they stay its author, and add your work on top. UseCo-authored-byonly for code you rebuilt rather than reused. If it's wrong or stale, fix the row fresh and say why on that PR, then close it with a credit note. - A fix not run against what it targets (the Desktop app, a gateway serving several profiles, a real bot platform, macOS launchd, an install upgraded from an older version) uses
Refs, notFixes, and the PR says what still needs a live retest. - Steps, evidence and code locations are in the triage comments linked in each row and under each section of the tracker's open findings.
Findings
Done (Oct 18): all seven lane PRs are merged to main (#140967, #140968, #140969, #140970, #140971, #140972, #140973). Fixed rows are in the tracker's Fixed on main continuation. @dokterdok's round-2 review fixes for lanes 1, 2, 3a, 3b and 5 did not go in with the lanes; they are on fix/pkg10-followups-main, not yet on main.
Status: 🟡 static read or user report, not reproduced yet · 🟢 fixed on main · ⚪ not reproduced or closed on main
Lane 1: The gateway process: restart, idle exit, parked profiles and managed workers
What the owning gateway does around its own lifetime and the profiles it serves. GW-14 is the macOS launchd relaunch after a downgrade stop (gateway/runtime_downgrade_exit.py), GW-15 counts /bg, /btw and preview side agents as owner work (gateway/session_tui_side.py), GW-16 is idle exit on a multiplexed gateway (gateway/run_idle_exit.py), and GW-17 is a parked secondary profile acknowledging messages it never admits; build on GW-12's notice (#140232, merged). PLG-13 is built-in tools registering into the launch home only, so other profiles get none. KB-6 and KB-7 are managed-worker identity and admission timing. T23's cause is known (a lock-order deadlock inside logging, found in #140230's CI run); fix the ordering, not the timeout.
| ID | Finding | Severity | Status | Open PR by an outside contributor |
|---|---|---|---|---|
| GW-17 | #140564 (multi-profile): messages for a parked secondary profile are acknowledged and lost (relay frames acked with nothing admitted; a coalescing webhook answers 202 coalesced, drops the batch, then 200 duplicate on retry), and serving it again after a rescan leaves its sessions runtime_draining. Fix: refuse retryably while parked and fully re-arm the authority on rescan. Related: GW-12's notice for direct adapters (#140232). |
broken | 🟢 fixed on main by #140967 (25eb0bb8) |
#140565 (draft, @dokterdok) |
| GW-14 | #140418 (macOS): a confirmed runtime downgrade stops the gateway with exit 0, and the launchd plist hermes gateway install ships doesn't relaunch on exit 0, so the gateway stays down. gateway/runtime_downgrade_exit.py assumes the service manager relaunches, which holds under systemd only. Fix: a nonzero restart code on a downgrade stop, or a plist that relaunches on any exit. |
broken | 🟢 fixed on main by #140967 (25eb0bb8) |
#140419 (draft, @strzhao) |
| GW-15 | #140375: a running /bg task, /btw question or Desktop preview restart is killed by a planned gateway restart (hermes update, service restart, SIGUSR1) or idle exit, and its result never arrives. gateway/session_tui_side.py keeps side agents in a private set the owner's drain doesn't count. Fix: count side agents as owner work. |
broken | 🟢 fixed on main by #140967 (25eb0bb8) |
#140378 (draft, @dokterdok) |
| GW-16 | #140509: an auto-started multiplexed gateway never idle-exits after a secondary profile used a local session. _messaging_busy (gateway/run_idle_exit.py) filters Platform.LOCAL out of the launch profile's adapters only. Reproduced by the reporter's test on main. |
degraded | 🟢 fixed on main by #140967 (25eb0bb8) |
#140510 (draft, @dokterdok) |
| PLG-13 | Multiplexed gateway: sessions routed to a non-launch profile get zero tools. Built-in tool modules first imported from a plugin-loading frame register into the launch home's overlay, so other homes see none of them (broader than catalog-plugin discovery, #140238, closed in favour of this tracker). | broken | ⚪ not reproduced on main b3c28838095 (package 10, #140967): three probes (built-in imported from plugin code, a real boot, a plugin that imports model_tools) all register built-ins globally; register() attributes a tool to its own module (tools/registry.py:700-733), never the importing plugin. Ask the reporter which plugin re-registers built-ins with ctx.register_tool. |
— |
| KB-6 | #140580 (macOS): after a clock correction (NTP step, sleep/wake) every managed worker is refused permission_denied, so every Kanban worker exits at spawn until a gateway restart. verify_worker_identity compares psutil create_time() by exact equality. |
broken | 🟢 fixed on main by #140967 (25eb0bb8) |
#140612 (draft, @liuhao1024) |
| KB-7 | Kanban: kanban.run's admission ACK uses the default 30 s RPC wait; if it arrives late the submitter exits with "Gateway connection failed", and a worker that binds later can be ended by the submitter-liveness watcher, leaving the admission unknown. Client timeout boundary probed; the server-side cause isn't reproduced. |
degraded | ⚪ closed: the client timeout is fixed in package 10 (#140967). The server-side boot delay didn't reproduce on main. Reopen with a fresh report if it recurs. |
— |
| T23 | tests/gateway/test_runtime_listener_supervision.py hung once on CI (killed at 600 s); a fixture now dumps thread stacks at 240 s. Cause found in #140230's CI run (not fixed there; a pre-existing race): a lock-order deadlock inside logging in test_listener_failure_stops_bootstrap_background_threads. uvicorn's dictConfig (build_listener_server) holds the logging module lock and waits on a handler lock, while the QueueListener thread holds that handler lock as hermes_logging builds a per-home file handler, which needs the module lock. |
flaky | 🟢 fixed on main by #140967 (25eb0bb8) |
— |
Lane 2: Clients that fall behind, reconnect or wait
One fix type: a client that misses events, sees a slow reply or reconnects must recover from the gateway, not fail the turn. GW-18 is tui_gateway/ws.py running one request at a time per connection; CLI-35 and CLI-37 are the classic CLI and Kanban client treating a replay gap or a full event queue as a lost connection; ACP-19 refuses from a stale cached snapshot; RT-37 is Desktop retrying SESSION_NOT_OWNED with no backoff; LC-23 and LC-24 are the API session door (an overflow reset that collides with the door's restore, and missing tool frames on chat/stream). The classic CLI's files are shared with #139158: package 1's #140675 changes _resubscribe in hermes_cli/gateway_connection.py, so CLI-35 must not edit that function.
| ID | Finding | Severity | Status | Open PR by an outside contributor |
|---|---|---|---|---|
| GW-18 | #140667 (Desktop, large sessions): session.control.read, session.interrupt and session.resume time out after 30 s and every socket in the window closes (send_failed_after_response). They queue behind session.context_breakdown, which rebuilds the prompt over the whole transcript; tui_gateway/ws.py runs one request at a time per connection. Fix: a long-handler pool, a per-revision cache, and no socket close for a late reply. |
broken | 🟢 fixed on main by #140968 (f0892ef9) |
#140671 (draft, @KoNit-K) |
| CLI-35 | #140388: a client that falls behind a long answer (past 16,384 frames / 4 MiB) gets one session.replay_gap and treats it as a failed turn: the classic CLI never re-subscribes and its next prompt hangs, -z / stream-json fail with session_replay_gap, and ACP stops its event pump. Fix: re-subscribe and reload the transcript. |
broken | 🟢 fixed on main by #140968 (f0892ef9) |
#140389 (draft, @dokterdok) |
| CLI-37 | #140597 (classic CLI, Kanban workers): after Ctrl-Z during a long streamed answer, fg reports "turn outcome is unknown" and the next prompt fails with no close frame received. The client's 4,096-frame event queue counts as a lost connection when full; a Kanban worker whose card streams more than 4,096 events stops the same way. |
broken | 🟢 fixed on main by #140968 (f0892ef9) |
#140598 (draft, @dokterdok) |
| ACP-19 | #140521: ACP keeps refusing a conversation's next prompt after its lost turn was discarded, repeating the /discard instruction. GatewayACPAgent.prompt refuses from a cached snapshot that isn't refreshed if the discard happened while the link was down. Fix: re-read session.info before refusing. |
broken | 🟢 fixed on main by #140968 (f0892ef9) |
#140523 (draft, @dokterdok) |
| RT-37 | #140385 (Desktop): on a Bot Chat the gateway also owns, the user's own turns are refused SESSION_NOT_OWNED while a gateway turn runs; process notices retry with no backoff (3,349 refusals in 46 s), and a turn that then succeeds shows "Turn failed". The interim design from ec5ee66 with no tracked fast-follow until now. |
broken | 🟢 fixed on main by #140968 (f0892ef9) |
#140391 (draft, @Wenfengcheng) |
| LC-23 | #140365: an API session that overflows its context answers HTTP 500 on every later request (POST /api/sessions/{id}/chat, the hermes peer dm transport). The messaging auto-reset now applies to API turns and collides with the API door's restore (admission_conflict). |
broken | 🟢 fixed on main by #140968 (f0892ef9) |
#140368 (@dokterdok) |
| LC-24 | #140551 (API server): POST /api/sessions/{id}/chat/stream sends no tool.started / tool.completed / tool.failed frames, though the docs list them and it sent them before the merge. gateway/session_api_turn.py subscribes only tool_progress_callback. |
degraded | 🟢 fixed on main by #140968 (f0892ef9) |
#140552 (draft, @dokterdok) |
Lane 3: Credentials, grants and per-session settings that don't stick
A setting, key or grant that a session or profile should keep is dropped or never applied. LC-20 is launch secrets released while a /branch child still uses them (release_launch_secrets); #140264 was meant for package 8, which closed without it. CLI-36 is /model --once (a one-turn override on the admission, not a shared-session switch), MP-16 a reasoning pick on a profile-following Bot Chat, CLI-39 the Docker backend's per-session cwd, CMD-2 the gateway refusing /voice tts by name (the classic CLI's own /voice is #139158's T1; leave it). CFG-11 is a managed worker's first "Always" approval. PLG-12, DB-5 and DB-6 are grants for secondary-profile and profile-registry routes; fix DB-5 and DB-6 together. PLG-12 has three outside PRs: pick the best, credit the others when closing them.
| ID | Finding | Severity | Status | Open PR by an outside contributor |
|---|---|---|---|---|
| LC-20 | #140270: deleting a conversation started with a launch-only key (--api-key, or a model alias with its own key) breaks its /branch children: the branch's next turn fails before any request, and /compress refuses with launch_credentials_unavailable. A branch copies its parent's frozen policy (hermes_state_mutation_branch.py::_child_policy), and gateway/session_policy.py::release_launch_secrets drops every key slot named after the deleted id, whoever still references it. Both files are new with #106742. |
broken | 🟢 fixed on main by #140969 (2b2672b1) |
#140264 (@dokterdok) |
| CLI-36 | #140412: classic CLI /model B --once switches the shared session's model for every viewer, then writes the old model back; if that write is refused the session stays on B. Fix: a one-turn override on the admission. |
broken | 🟢 fixed on main by #140969 (2b2672b1) |
#140413 (draft, @dokterdok) |
| MP-16 | #140446: on a Bot Chat that follows its profile's config (every Desktop-created Bot Chat), a reasoning change is acknowledged and never applied; the next turn re-reads the profile's level. Fix: store the pick as a session override that survives profile following, as a model pick does. | broken | 🟢 fixed on main by #140969 (2b2672b1) |
#140447 (draft, @dokterdok) |
| CLI-39 | #140665 (Docker terminal backend): concurrent one-shot hermes chat runs lose their workspace. With container_persistent: false no /workspace bind; with true every session shares the first session's cwd. The client's cwd no longer reaches the session's terminal overrides now that turns run in the gateway. Same report: 201 multiplexed profiles boot in 2 min 14 s, past the client's 60 s ensure timeout. |
broken | 🟢 fixed on main by #140970 (ccee4ca9) |
— |
| CMD-2 | #140398: /voice tts on a local session answers "Auto-TTS enabled", then sends every reply to the TTS provider and discards it (a paid call per reply); Ink's /voice off flips a different switch. Fix: refuse /voice tts by name on local sessions. |
degraded | 🟢 fixed on main by #140969 (2b2672b1) |
#140399 (draft, @dokterdok) |
| CFG-11 | #140459: the first "Always" approval in a managed worker (Kanban task, safe mode, --ignore-user-config) never reaches config.yaml on a fresh profile without a command_allowlist key, so the next task asks again. |
degraded | ⚪ closed: the --ignore-user-config path is fixed in package 10 (#140969). The ordinary managed-worker case isn't reachable from a CLI --base-url worker (refused unsupported_managed_policy), so no fix is owed here. |
#140460 (draft, @dokterdok) |
| PLG-12 | #140499: user dashboard plugins' mutating endpoints always answer 401 when a secondary profile is selected. PLG-3's per-profile plugin host strips the gateway credentials, so _require_token can never pass. A regression from the PLG-3 fix, not #106742 itself. |
broken | 🟢 fixed on main by #140970 (ccee4ca9) |
#140513 (draft, @Wenfengcheng), #140514 (draft, @liuhao1024), #140524 (@iamdgarcia) |
| DB-5 | #140345 (Desktop): deleting or renaming a profile returns 403 profile_scope_mismatch while a gateway runs; the native grant path (hermes_cli/dashboard_auth/native_http.py) has no grant for profile-registry writes. (#140345 closed as a duplicate of its tracker report) |
broken | 🟢 fixed on main by #140970 (ccee4ca9) |
— |
| DB-6 | #140346 (Desktop): in "All profiles" scope the Profiles screen 403s for every profile (GET/PUT /api/profiles/<name>/soul); the registry route appends the ambient profile to a path that already names one. Fix with DB-5. (#140346 closed as a duplicate of its tracker report) |
broken | 🟢 fixed on main by #140970 (ccee4ca9) |
— |
Lane 4: Desktop session lists, history and identity across compression
One cluster: a session must keep one identity, and its full history, across compression, rewind, adoption and paging. RT-39 (resume shows only the summary) and RT-44 (a rewind above a compaction boundary empties the transcript) are the history half; LC-22 (rename and archive of a cold compressed session) and CLI-38 (subagents lost when compression rotates the session id) the identity half; RT-41 (pre-cutover Desktop sessions can't be resumed), RT-42 (paged all-profiles list), RT-43 (ws_orphan_reap mid-turn), RT-36 (deleted sessions come back; read the attached logs and retest on a build with #140191 first), RT-38 (Bots tab after update) and RT-45 ("All profiles" switched off at boot) are the session-list half. #140450 for RT-39 also edits Desktop slash-session-commands.ts, gateway/session_controls.py and gateway/session_tui_ops.py, which package 3's #140382 changes; take only its display-history fix.
| ID | Finding | Severity | Status | Open PR by an outside contributor |
|---|---|---|---|---|
| RT-43 | #140642 (Desktop): a conversation is permanently stuck after a remote viewer disconnects mid-turn: the session is stamped ws_orphan_reap while its turn runs, the stale-entry recovery gets admission_conflict, and the route is later repointed to an empty replacement, so every resume fails. |
broken | 🟢 fixed on main by #140971 (0952996a) |
— |
| RT-39 | #140449: resuming a compressed conversation (Ink /resume, Desktop re-focus and replay-gap re-snapshot, one-shot --resume) shows only the summary and the last exchange, though every turn is still stored. local_history returns the compacted working set as the display snapshot. |
broken | 🟢 fixed on main by #140971 (0952996a) |
#140450 (draft, @dokterdok) |
| RT-44 | #140635 (Desktop): editing, restoring or regenerating a message above a compaction boundary empties the live transcript. session.mutate rewind accepts an archived target and deactivates every later active row, the summary included. |
broken | 🟢 fixed on main by #140971 (0952996a) |
#140636 (draft, @rodricksz4h5) |
| LC-22 | Rename and archive of a cold local session that was compressed or reset fail with storage_unavailable: _owner_ref remaps to the lineage owner only for delete, so authorize() restores by the child's physical id. Same class as LC-12 on the control-mutation door. |
broken | 🟢 fixed on main by #140971 (0952996a) |
— |
| CLI-38 | #140652 (suspected): after a compression rotates the session id, background subagents vanish from the monitor (parent_id: null) and their completions are never delivered, so the parent stalls. Not yet A/B tested against pre-merge d04056d609b. |
degraded | ⚪ not reproduced as a compression bug (package 10, #140971): completions after a compression rotation are delivered in all four probe cases. The empty Ctrl+T monitor is CLI-12 (the classic CLI's monitor reads its own process; children run in the gateway), fixed by #140677. parent_id: null is normal for top-level children. |
— |
| RT-41 | #140506 (Desktop): a pre-cutover desktop-created session (session_key = NULL, no gateway_routing entry; 282 rows for the reporter) can't be resumed: session.resume returns not_found and Desktop loops a "Resume failed" toast. The authority has no cold-adoption path for source='desktop' rows. |
broken | ⚪ not reproduced on main (package 10, #140972): a pre-upgrade Desktop row (source='desktop', session_key NULL) resumes by id through the gateway authority (resolve_local_target → adopt_legacy_session, landed in f9b5bd24c2); probed un-ended, titled, model-config and profile_name='default' rows. A ticket for one profile resuming another profile's row still gets a named refusal by design. |
— |
| RT-42 | #140518 (Desktop): the all-profiles Sessions list can repeat a pinned chat and drop another once a profile passes 500 sessions; Archived paging stops early, and two profiles with the same session id lose one chat. | degraded | 🟢 fixed on main by #140972 (f1a7405d) |
#140519 (draft, @dokterdok) |
| RT-36 | #140277: in Desktop (v0.22.2, Windows 10), deleted or archived sessions come back in the session list after it refreshes, and the deleted ones can't be opened. No cause yet; the report has logs attached. #140191 (merged) closed one path, a stale routing save restoring a deleted secondary-profile route; whether this report is that path needs the logs read and a retest on a build that includes #140191. | broken | ⚪ not reproduced on main (package 10, #140972): deleted and archived rows stay out of the list through the real HTTP routes across repeated refreshes, and #140191's tests pass. Report was on v0.22.2, before the gateway runtime and #140191; its logs expired. Reopen with fresh logs if it recurs. |
— |
| RT-38 | #140417 (Desktop, probable): after hermes update the Bots tab shows only the default profile; the roster logs answered=- on every refresh, so profiles.list carries no install_id or fails. |
broken | 🟢 fixed on main by #140972 (f1a7405d) |
— |
| RT-45 | Desktop switches "All profiles" off by itself at boot: a silent source restore is treated as a user switch (follow-up by @sryimnoob123 on an earlier report). | degraded | 🟢 fixed on main by #140972 (f1a7405d) |
#140276 (@sryimnoob123) |
Lane 5: Messaging order and Bot Chat
One fix type: what arrives in a chat runs in arrival order through the durable FIFO, exactly once, on the conversation it was sent to. MSG-23 (media staged before admission), MSG-25 (a message sent right before /new), MSG-26 (one-at-a-time platforms stall on a busy burst) and MSG-27 (slash commands skip the FIFO) are ordering; MSG-24 is a cancelled media capture that leaks its lease; MSG-21 and MSG-22 are Bot Chat creation and adoption, and share one outside PR (#140471), so fix them together. These need a real bot platform for the live retest; the unit tests use the existing adapter fixtures.
| ID | Finding | Severity | Status | Open PR by an outside contributor |
|---|---|---|---|---|
| MSG-23 | #140453: a text sent right after a photo or video can run first, without the media: media is staged in a worker thread before admission. Fix: reserve the chat's FIFO slot on arrival. | broken | 🟢 fixed on main by #140973 (54809183) |
#140454 (draft, @dokterdok) |
| MSG-25 | #140548: a message sent right before /new can run in the new conversation, and neither /new's Stop nor /stop reaches it; the turn resolves the rotated route during setup. |
broken | 🟢 fixed on main by #140973 (54809183) |
#140549 (draft, @dokterdok) |
| MSG-26 | #140538 (Signal, IRC and other one-at-a-time platforms): photos sent one by one or a split text during a turn become separate follow-up turns, and the reader stalls about 0.38 s per message: dispatch_busy_burst waits for the burst's durable commit. |
degraded | 🟢 fixed on main by #140973 (54809183) |
#140539 (draft, @dokterdok) |
| MSG-27 | #140572: /queue, /steer (fallback), /plan, /learn, /init, /blueprint and skill commands run ahead of messages already waiting in the chat (A, B, /queue C runs A, C, B): only plain text enters the durable FIFO. |
broken | 🟢 fixed on main by #140973 (54809183) |
#140573 (draft, @dokterdok) |
| MSG-24 | #140520: a bot message cancelled while its image or video is being copied can leave the retained media file and its capture lease behind forever. | degraded | 🟢 fixed on main by #140973 (54809183) |
#140522 (draft, @dokterdok) |
| MSG-21 | #140374: peer DM into a profile that has never had a local Bot Chat fails permanently (Bot Chat admission refused: not_found): _target() finds a legacy api_ "Bot Chat" row and fails adoption, the peer grant has no session:create, and each retry mints another api_ row. (#140374 closed in favour of this row) |
broken | 🟢 fixed on main by #140973 (54809183) |
#140471 (draft, @dokterdok; also MSG-22) |
| MSG-22 | #140470: a Bot Chat created first by a bot delivery, cron job, the CLI or an upgrade stays on that moment's model, endpoint and key, and Desktop later opens it by title. Only Desktop sets follow_profile_config. |
broken | 🟢 fixed on main by #140973 (54809183) |
#140471 (draft, @dokterdok; also MSG-21) |
Not in this package
- Overlap with work in an open package: CLI-34 (its fix and fix(cli): re-supply the launch key when the classic CLI resumes a session #140348 change
_resubscribe, which package 1's fix(cli): a /resume or /sessions switch subscribes the session it lands on (CLI lane 1, salvage #138700) #140675 is changing); RT-40 (Desktop/undoand/retryafter a lost reply, the same handler as package 3's T12, under review in fix(gateway,desktop): /undo and /retry mid-reply say to stop first; editing an interrupted message replaces it #140382). - Out of this cutover's scope: DB-7 (Desktop in URL, Cloud or SSH mode talks to standalone
hermes serve; outside PR fix(gateway): replay missed events and prompts after a legacy reconnect #140456). Whether this tracker takes it needs a maintainer call. - Need a maintainer decision, or someone is already on it: the rows package 9 listed (GW-1, GW-10, F1, T7, MSG-15, MP-13, ACP-7, T22, TUI-14, TUI-16, CLI-9, T9, MP-12, RT-21, KB-2).
- These rows stay on Tracking: one gateway owns every local session (#106742) — post-merge fixes #134889.
Done when
Every row has a merged PR, a live-check result, or a note on #134889 that it doesn't reproduce on main.
Activity
dokterdok commentedon Oct 17, 2026
Notes on the rows that list my PRs, for whoever runs this package.
GW-17 (#140564, #140565): the row was written before #140232 merged.
mainnow fixes: fix(gateway): keep booting after a deleted Bot Chat's tombstones expire #140232 (8ce2a4f876) fixed the relayprofile_mismatchACK, the/p/<parked>/webhook 503, the coalesced id release, the staleLOCALadapter, and API and native recovery at the rescan. A parked profile's relay and webhook messages are acknowledged and lost, and serving it again leaves its sessions stuck #140564 is updated with what's left.main. A live frame gets no redelivery at all.mainas one commit,a88ea4e2de.profile_routessends to a parked profile (finding 2 of the review)./p/<parked>/API doors and shared-listener callbacks, and for any unserved webhook prefix.Not in any package: finding 3 of the same review.
api_serverid. So a caller-named session id is refused forever after an auto-prune.mainbefore fix(gateway): keep booting after a deleted Bot Chat's tombstones expire #140232 accepted that id again after the 7-day horizon.Overlaps:
_resubscribe, and it merges cleanly with fix(cli): a /resume or /sessions switch subscribes the session it lands on (CLI lane 1, salvage #138700) #140675._resubscribe(thesession.resumecall and the_GONEcheck). Whichever lands second needs a one-line rebase. I'll do fix(cli): re-supply the launch key when the classic CLI resumes a session #140348's if fix(cli): a /resume or /sessions switch subscribes the session it lands on (CLI lane 1, salvage #138700) #140675 lands first.81e4666af9is the display-history fix, and it can be taken alone.84527993e2keeps Desktop's/undoand/retryand the owner's/rollbackrewind on live rows. fix(gateway,desktop): /undo and /retry mid-reply say to stop first; editing an interrupted message replaces it #140382 doesn't cover that, and both commits merge cleanly with fix(gateway,desktop): /undo and /retry mid-reply say to stop first; editing an interrupted message replaces it #140382.not_foundwhen a non-local row already holds the title) is a different bug on the same door. fix(gateway): make a Bot Chat follow its profile, whoever created it #140471's body says so, and no PR of mine covers it.Rebased: #140413 (CLI-36), #140450 (RT-39), #140522 (MSG-24) and #140471 (MSG-22) conflicted with
main. They're now rebased ontoe6f57427c1, and each body notes the conflict and the test results. Every PR of mine listed here now merges cleanly.Already live-retested (results are in each PR's body): GW-15 #140378, GW-16 #140510, CLI-35 #140389, CLI-37 #140598, ACP-19 #140523, LC-23 #140368, MP-16 #140447, RT-39 #140450. The other PRs' bodies say what still needs a live retest.
145 remaining items
fix(gateway): key a secondary profile's side agents and worker turns …
fix(docker): remove idle workspace containers when they cannot be re-…
fix(gateway): keep the session's workspace container for a preview re…
fix(cli): send a --once pick through an alias named like the session …
fix(gateway): keep the session's route for a --once alias with no end…
fix(gateway): a serial reader reads on while an earlier input of the …
test(gateway): the restart-behind-a-capture test's next owner runs wh…
dokterdok commentedon Oct 18, 2026
@teknium1 lane 5 also went in without my round-2 fix, the serial reader stall (
512107c06e). I added it tofix/pkg10-followups-main, with its optional test-only commit, and rebased the branch ontomainat54809183676.That's nine commits now, each standing alone. On that base, the nine fixes' own suites and the review probes pass (126 tests), and
scripts/checkpasses.mainc4d6fb6c9925b180d6cb/bgin the default container42d1314f75persist_across_processes: falseleaks idle containersd22e340e959cbc6dd2a2--oncealias on the session's endpoint1b0ea01458--oncealias drops the session's route (pairs with the row above)4d1df09d6aeeadb427733b2b074eb0The reasons and tests for each are in that lane's fix comment.
Refs #134889
fix(gateway): starting the API listener no longer silences the log files
fix(tui): an owner error after its commit is unconfirmed, not "nothin…
fix(gateway): key a secondary profile's side agents and worker turns …
fix(cli): send a --once pick through an alias named like the session …
fix(gateway): keep the session's route for a --once alias with no end…
fix(gateway): a serial reader reads on while an earlier input of the …
test(gateway): the restart-behind-a-capture test's next owner runs wh…