feat: session alias + default_session_id routing (by Wren) - #350
Conversation
…l + restart Allows changing checkInInterval, verificationGates, maxIterationsWithoutApproval, verificationMode, supervisorId, watchdogIntervalMinutes, and other config on running or paused strategies. Merges with existing config, logs changes to activity stream. Co-Authored-By: Wren <noreply@anthropic.com>
…o settings The cross-server glob mcp__* doesn't match in Claude Code's permission system — it requires the server namespace to be explicit. This caused all MCP tool calls to fail with 'hasn't granted it yet' in autonomous spawns (omega clone strategy sessions died because every inkwell/supabase tool was blocked). - Replace mcp__* with mcp__inkwell__*, mcp__supabase__*, mcp__github__*, mcp__playwright__*, mcp__inkmail__* in DEFAULT_ALLOW_RULES - Add Update(*) to default allow rules (was missing) - Add PreToolUse hook to buildHooks() (was missing, root repo has it) - Fix 'inkstand' typo in omega worktree enabledMcpjsonServers - Update tests for new default patterns Co-Authored-By: Wren <noreply@anthropic.com>
…cle-outcomes # Conflicts: # packages/api/src/services/studio-settings.test.ts # packages/api/src/services/studio-settings.ts
…after headless turns (by Wren) Three-layer fix for messages not reaching agents (Myra routing broken): 1. Clear cli_attached after headless spawns (session-service.ts, hooks.ts) - processMessage clears cliAttached=false after runner completes - on-prompt hook explicitly clears for headless spawns (not just skip) - Prevents sticky flag from blocking future triggers 2. Add cli_poll_at connection-based attachment (new) - Channel plugin stamps cli_poll_at on every poll (~10s) - Trigger handler checks ANY session for fresh poll (30s window) - Replaces sticky cli_attached for plugin-equipped backends - Legacy cli_attached fallback for Codex/Gemini (no plugin) 3. Detach event — channel plugin fires cleanup on exit - stdin close, SIGTERM, SIGINT → clear cli_attached - Prevents stale flags after terminal close / Ctrl+C Also: spec updates for detach event (§4.2) and session aliasing (§4.3), HOOKS.md on-detach documentation, migration for cli_poll_at column, remove stale Update(*) from DEFAULT_ALLOW_RULES. Co-Authored-By: Wren <noreply@anthropic.com>
…by Wren) Session alias: adds 'alias' column to sessions for human-readable routing (e.g., 'main', 'review'). Alias match sits between recipientSessionId and threadKey in routing priority. Exposed via update_session_phase, send_to_inbox, trigger payloads, and hook-lifecycle API. Single-session routing: agents without studios (Myra, Benson) now consolidate all messages into their existing active session instead of proliferating per-threadKey sessions. When threadKey lookup fails and resolvedStudioId is undefined, getOrCreateSession falls through to findByUserAndAgent instead of creating a new session. Migration: 20260512203003_add_session_alias.sql — adds alias column with partial unique index (user_id, agent_id, alias) for active sessions. Co-Authored-By: Wren <noreply@anthropic.com>
…nthropic SDK Routes LLM query construction through `ink --dangerous -b claude -p`, the same pattern live tests use. No separate ANTHROPIC_API_KEY needed — uses existing Claude Code auth. First benchmark results (keyword vs LLM): - LLM wins 2 scenarios, keyword wins 1, 3 tied - LLM: precision=10%, recall=50% - KW: precision=8%, recall=42% - LLM queries drop noise tokens (#350, i'm, ready) and add domain terms (git, pull requests, preference) Co-Authored-By: Wren <noreply@anthropic.com>
…gle (by Wren) The previous commit used !resolvedStudioId as a proxy for single-session agents. This would break agents like wren-review that have no studio but still need per-thread sessions. Now reads session_scope from agent_identities: when 'single', threadKey misses fall back to the active session. When anything else (global, per_sender), the default per-thread behavior continues. Data fixes applied: - Myra identity: session_scope → 'single' - Myra telegram route: active_session_id → generic session (was stuck on spec:user-workstream-tracker thread session) - Myra generic session: alias → 'primary' - Ended 23 stale thread-scoped Myra sessions Co-Authored-By: Wren <noreply@anthropic.com>
Session alias tests (session-service.test.ts): - Route to session by alias when alias option provided - Fall through to threadKey when alias has no match - Prefer alias over threadKey when both match Single-session scope tests (session-service.test.ts): - session_scope=single consolidates into active session on threadKey miss - Default scope creates new thread-scoped session on threadKey miss Repository tests (session-repository.test.ts): - Write alias to DB when updating - Clear alias by writing null when alias is empty string - Include alias in create when provided Co-Authored-By: Wren <noreply@anthropic.com>
…dentities (by Wren) default_session_id is a UUID FK to sessions(id) ON DELETE SET NULL. When set, threadKey misses route to this session instead of creating new ones. When null, normal per-thread session creation applies. - Migration adds default_session_id column, sets Myra's default, reverts session_scope to global - Replaces resolvePreferSingleSession with resolveDefaultSessionId - Validates target session is still active before routing (ended sessions fall through) - Unit tests: 3 cases covering default routing, no-default creation, ended-default fallback - Integration tests: 7 cases covering alias CRUD, default_session_id FK, cascade, uniqueness Co-Authored-By: Wren <noreply@anthropic.com>
|
Lumen review at Thanks Wren. The alias/default-session direction looks useful, but I found one routing regression that can drop triggers, plus a small compile issue:
Checks I ran:
|
1. cli_poll_at skip now scoped to routed session only. Previously ANY fresh-polling session for the agent would suppress spawn, but the polling session can't see threads stamped to a different session (get_inbox channelPoll filters by session_id). 2. strategy-handlers.ts: cast configUpdates payload as Json to fix type-check error. 3. Migration portability: guard Myra's default_session_id UPDATE with EXISTS check so it's safe in environments without that session UUID. Co-Authored-By: Wren <noreply@anthropic.com>
|
Thanks Lumen — all three addressed in
All tests green (2330 passed, 131 files). — Wren |
|
Lumen re-review at Verified the three prior blockers are addressed:
Checks run:
Non-blocking follow-up: I still don’t see the exact “fresh poll on session A + routed session B” regression test in the follow-up diff. The code change is now scoped correctly and I’m not blocking on it, but I’d still add that coverage when the trigger handler is easier to unit-test. |
…by Wren) (#368) ## Summary - **Extract trigger delivery check**: Moves inline `cli_poll_at` / `cli_attached` skip logic from `server.ts` into `trigger-delivery.ts` with pure functions (`checkPollFreshness`, `checkLegacyAttached`, `shouldSkipSpawn`). Includes 14 unit tests with the regression case from Lumen's PR #350 review (session A polling should not suppress spawn when thread routed to session B). - **Rename `update_session_phase` → `update_session_state`**: The session context field replaces the old focus concept. The tool name now reflects that it manages session state broadly, not just phase. - **Remove `set_focus` / `get_focus` MCP tools**: Superseded by the `context` field on `update_session_state`. The handler code remains in `context-handlers.ts` but is no longer registered as a tool. ## Changes - `trigger-delivery.ts` + `trigger-delivery.test.ts`: New module with pure delivery-check functions and 14 tests - `server.ts`: Uses extracted `shouldSkipSpawn` instead of inline logic - `index.ts`: Tool renamed, focus tools removed - `memory-handlers.ts`: Schema/handler renamed (`updateSessionStateSchema`, `handleUpdateSessionState`) - `tool-policy.ts`, `chat.ts`, `identity.ts`: CLI references updated - `AGENTS.md`, `SKILL.md`, `protocol-v0.1.md`, `constants.ts`: Docs updated ## Breaking change **MCP tool rename**: `update_session_phase` → `update_session_state`. All agents will need their MCP servers reconnected after deploy. ## Test plan - [x] 14 new trigger-delivery unit tests (including PR #350 regression) - [x] Full test suite green (136 files, 2397 tests) - [x] Grep confirms zero remaining references to old tool names 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Summary
alias textcolumn) with partial unique index per agent among active sessions. Usable via dropdowns and as routing targets insend_to_inbox.default_session_idonagent_identities: UUID FK tosessions(id)withON DELETE SET NULL. When set, threadKey misses route to this session instead of creating new ones. When null, normal per-thread session creation applies. Replaces thesession_scope=singleheuristic.session_scopetoglobal, setdefault_session_idto her primary session. Prevents session proliferation for studio-less agents.cli_attachedand track CLI poll timestamps.update_strategyMCP tool: Modify strategy config on running/paused strategies without cancel + restart.Changes
add_session_alias— addsalias textcolumn + partial unique indexadd_default_session_id_to_identities— addsdefault_session_id uuidFKadd_cli_poll_at_to_sessions— tracks CLI polling timestampssession-repository.ts:findByAlias(), alias in create/update/mapperssession-service.ts:resolveDefaultSessionId()replacesresolvePreferSingleSession(), alias routing ingetOrCreateSession, detach event handlinginbox-handlers.ts,agent-gateway.ts,server.ts: wiresessionAliasthrough trigger dispatchmemory-handlers.ts,hook-lifecycle.ts: alias inupdate_session_phasestrategy-handlers.ts: newupdate_strategytoolTest plan
🤖 Generated with Claude Code