feat(interactions): Codex read-only Feed telemetry, worktree identity, daemon health tolerance - #113
Conversation
The daemon health-checked each project service with a 1000ms timeout and hard-restarted it (SIGTERM/respawn) on a single failure. Under load a busy event loop can miss one ping, so healthy services were being killed in a restart loop — dropping SSE streams and breaking in-flight interaction hooks (observed as repeated 'health check failed: request timed out after 1000ms' followed by terminate/respawn). Raise the timeout to 2500ms and only restart after 3 consecutive failures (counter resets on any success), so a transient stall no longer churns the service. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codex's PermissionRequest hook used the same blocking long-poll as Claude
(resolvePermissionRequestOutput, 115s). Unlike Claude — which still renders its
native approval prompt while the hook blocks — Codex suppresses its native
prompt and sits at 'Working / Running PermissionRequest hook' until the hook
returns, so the only way to decide was a remote Feed card. That makes the TUI
non-primary, which is unacceptable.
Mirror cmux's codex behavior (PermissionRequest = telemetry): the codex hook now
emits a needs_input event + sets attention (so the dashboard/Feed still shows
codex needs you) and returns {} immediately, deferring to codex's native prompt.
Claude's blocking/actionable path is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
So clients can show which project/worktree a permission prompt is from, include the hook's working dir (the worktree, or project root if none) in the interaction payload. cmux renders it as project/worktree in the Feed card header. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codex's native TUI owns the decision, but the prompt was invisible in clients. Add a non-blocking /agents/interaction/notify endpoint that emits a telemetry interaction alert (interaction.telemetry=true, with toolName/toolInputJSON and the worktree cwd) and flags attention, without registering a blocking interaction. The codex permission hook posts to it, then defers to the native prompt. cmux renders telemetry alerts as a non-actionable read-only row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hreshold The health-tolerance fix replaces a service only after 3 consecutive failed health checks (not the first). Update the two replacement tests to tolerate two misses and assert replacement on the threshold-crossing third. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThis PR makes daemon supervision tolerate transient project-service /health failures by counting consecutive misses and only replacing services after a threshold, and changes permission-request handling to emit non-blocking telemetry notifications with enriched metadata. ChangesHealth-Check Failure Threshold Resilience
Permission Request Telemetry and Interaction Notifications
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/daemon.ts`:
- Around line 594-596: projectHealthFailures can carry over stale failure counts
to a new PID; reset it whenever a service instance is replaced. In the spawn and
reap code paths that create or replace a project service (e.g., the
non-threshold spawn handler and the service reaper / reapService method), clear
the counter by calling this.projectHealthFailures.delete(projectId) or
this.projectHealthFailures.set(projectId, 0) right after you create or register
the new instance so the new PID starts with a fresh failure state.
In `@src/main.ts`:
- Around line 3559-3571: The telemetry call in the "permission-request" case
currently awaits postLiveProjectServiceJsonOrLocal and can throw, blocking
fallback output; make this a best-effort fire-and-forget (or catch-and-ignore)
so the hook always falls back to {}: do not let exceptions propagate from
postLiveProjectServiceJsonOrLocal called after summarizeClaudePermissionRequest
— either remove the await and let it run asynchronously or wrap the await in a
try/catch that logs/debug-ignores errors and returns immediately; ensure
sessionId, summary and payload still get passed but any thrown error from
postLiveProjectServiceJsonOrLocal does not affect the surrounding
"permission-request" case behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 60828c17-eccd-4e37-8b3f-e926714d9053
📒 Files selected for processing (5)
src/daemon.test.tssrc/daemon.tssrc/main.tssrc/metadata-server.tssrc/project-events.ts
- daemon: reset projectHealthFailures in spawnProjectService so a fresh service instance never inherits the previous pid's failure debt (covers all spawn/ replace paths); also clear on stopProject. Keep the debt if termination fails. - codex hook: make the /notify telemetry post best-effort (.catch) so a transport failure never breaks the hook — it always defers to the native prompt. - /notify endpoint: tolerate malformed JSON (readJson catch) and reject/ignore a non-object payload.input, matching the /request handler's validation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Additional hardening from a parallel review pass (folded into 4fea99c):
Intentionally not changed:
|
Follow-ups to the agent-interaction bridge (#112), driven by live cmux Feed testing.
What's in here
{}, deferring to the native TUI.project/worktreea prompt is from./agents/interaction/notifyendpoint emits atelemetry: trueinteraction alert (toolName/toolInputJSON + worktree) without registering a blocking interaction; the Codex hook posts to it, then defers to the native prompt.Verification
yarn verify(full suite) green via pre-push.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements
Tests