fix(01): revise plan 01-03 based on checker feedback

Clarify subprocess persistence on session switch, mandatory auto-spawn
on /session, and message queueing delegation to ClaudeSubprocess.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikkel Georgsen 2026-02-04 14:35:53 +00:00
parent 0baaeb26b5
commit fd1c24d7c6

View file

@ -82,8 +82,7 @@ from telegram.claude_subprocess import ClaudeSubprocess
**Module-level state:**
- Create a `SessionManager` instance (singleton for the bot process)
- Create a dict `subprocesses: dict[str, ClaudeSubprocess]` to track active subprocess per session
- Track `active_session: str | None` at module level (or via SessionManager)
- Create a dict `subprocesses: dict[str, ClaudeSubprocess]` to track subprocess per session — **CRITICAL: this dict persists ALL session subprocesses, not just the active one. When switching from session A to B, the subprocess for A stays alive in `subprocesses['A']` with status "suspended" via SessionManager. This implements the locked decision: "Switching sessions suspends (not kills) the current process — it stays alive. No limit on concurrent live Claude Code processes."**
**New command: `/new <name> [persona]`**
@ -105,8 +104,8 @@ Handler: `async def switch_session_cmd(update, context)`
- Extract name from `context.args[0]` (required)
- Validate: if no args, reply with usage and list available sessions
- If session doesn't exist: reply "Session '<name>' doesn't exist. Use /new <name> to create it."
- Call `session_manager.switch_session(name)`
- If session has no running subprocess: spawn one (create ClaudeSubprocess, don't send message)
- Call `session_manager.switch_session(name)` — this marks the PREVIOUS session as "suspended" in metadata (subprocess stays alive in `subprocesses` dict)
- **MANDATORY auto-spawn:** After switching, check if `subprocesses.get(name)` is None or `not subprocesses[name].is_alive`. If so, create a new ClaudeSubprocess with session directory and persona, store in `subprocesses[name]`. This implements the locked decision: "Switching to a session with no running process auto-spawns Claude Code immediately." The subprocess idles waiting for first message.
- Reply "Switched to session '<name>'." (include persona if set)
**Modified message handler: `handle_message`**
@ -114,8 +113,8 @@ Handler: `async def switch_session_cmd(update, context)`
Replace the current implementation (which saves to inbox) with session-aware routing:
- If no active session: reply "No active session. Use /new <name> to start one."
- If active session exists:
- Get or create ClaudeSubprocess for session
- Call `await subprocess.send_message(update.message.text)`
- Get or create ClaudeSubprocess for session (auto-spawn if not alive)
- Call `await subprocess.send_message(update.message.text)` — **Note: ClaudeSubprocess handles internal message queueing via asyncio.Queue (Plan 02 design). If the subprocess is busy processing a previous message, `send_message()` queues the message and it will be sent after the current response completes. The bot handler does NOT need to check `is_busy` — just call `send_message()` and the subprocess manages the queue.**
- The on_output callback will need to send messages back to the chat. For Phase 1, create callbacks that send to the Telegram chat:
```python
async def on_output(text):