.maestro/playbooks/2026-02-23-Issue-Triage/2026-02-23-Root-Cause-Fixes/TRIAGE-08-Third-Party-Compatibility.md
Compatibility issues with Codex CLI, Cursor, and the viewer UI. Also fixes the /api/logs endpoint that reads entire files into memory, and the CORS error on settings save.
Issues resolved: #744 (Codex CLI), #838, #1049 (Cursor), #1203 (/api/logs OOM), #1029 (CORS), #1213 (session custom-title)
Fix Codex CLI compatibility (#744):
src/cli/handlers/session-init.ts, verify the handler doesn't throw on undefined prompt (not just empty string)session_id format differences — Codex CLI may use a different format than Claude CodeclaudeCodeAdapter now falls back through session_id → id → sessionId for session ID field. (2) getPlatformAdapter returns rawAdapter for unknown platforms instead of throwing (Codex, future CLIs). (3) session-init handler guards against undefined sessionId with graceful skip. (4) 10 new tests in hook-lifecycle.test.ts covering all cases. 1019 tests pass.Fix Cursor IDE integration (#838, #1049):
src/services/integrations/CursorHooksInstaller.ts for Cursor-specific issuessrc/cli/adapters/ and handle Cursor's formatcursorAdapter now tries conversation_id → generation_id → id for session ID and prompt → query → input → message for prompt field, plus workspace_roots[0] → cwd → process.cwd() for cwd. (2) handleSessionInitByClaudeId in SessionRoutes.ts now only requires contentSessionId — project defaults to 'unknown' and prompt defaults to '[media prompt]' when missing. (3) 16 new tests in hook-lifecycle.test.ts covering all Cursor adapter field fallbacks, undefined/null input handling, and formatOutput. 1036 tests pass. Fix /api/logs reading entire file into memory (#1203):
src/services/worker/http/routes/LogsRoutes.ts (around line 52-53), the endpoint reads the entire log file synchronouslyfs.createReadStream with a byte range or a simple readFileSync + split('\n').slice(-lines) — the latter is still better than reading 100MB+ into a JSON responsereadFileSync (full-file load) with exported readLastLines() function that reads from the end of the file in expanding chunks (64KB initial → doubles as needed → 10MB cap). Returns only the last N lines without ever loading the whole file into memory. Added 12 unit tests covering empty files, trailing newline handling, files larger than initial chunk size, and zero-line requests. 1048 tests pass, 0 regressions.Fix Settings CORS error (#1029):
Access-Control-Allow-Methods includes PUT, PATCH, DELETE (not just GET/POST)Access-Control-Allow-Headers includes Content-Typemethods: ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'] and allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'] to the CORS config in src/services/worker/http/middleware.ts. Added 6 new preflight CORS tests verifying PUT/PATCH/DELETE methods, Content-Type header, localhost allow-origin, and external origin rejection. 1054 tests pass, 0 regressions.Add session custom-title for agent attribution (#1213):
custom_title column to sdk_sessions table (migration)customTitle in the /api/sessions/init endpoint and store itcustom_title TEXT column to sdk_sessions in both MigrationRunner and SessionStore. (2) createSDKSession() in both modular (sessions/create.ts) and class (SessionStore) forms now accepts optional customTitle parameter — stored on insert, backfilled on idempotent re-call only if not already set. (3) /api/sessions/init extracts customTitle from request body and passes through. (4) getSessionById and getSdkSessionsBySessionIds include custom_title in SELECT. (5) Types updated: SessionBasic and SessionFull include custom_title: string | null. (6) 5 new tests in sessions.test.ts covering creation with title, null default, backfill, no-overwrite, and empty string handling. 1059 tests pass, 0 regressions. Run npm test and fix any failures