Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ The result is not a magical mind meld. It is a practical workflow: the agents on
- Stale Claude frontend attachments are probed and evicted instead of blocking a new Claude session indefinitely.
- Codex turns have a watchdog fallback, and the viewer/status model now distinguishes idle, busy, stale, and offline agent states.
- Codex resume/fork argument handling, active thread tracking, and app-server port cleanup are more robust, including LISTEN-only and Windows-aware process checks.
- Reliability guards now bound backup-agent timeout cleanup, daemon shutdown steps, and long-running Codex turns with visible ledger/status telemetry.
- The browser viewer remains the **Command Deck**: a read-only, color-coded, latest-first dashboard with clear history controls, task lanes, artifacts, policy state, and connection health.

## What It Helps With
Expand Down Expand Up @@ -724,7 +725,7 @@ Business value: the viewer and `ctxrelay status` no longer make a completed or s

Technical shape:

- Codex exposes `idle`, `busy`, `stale`, and `offline` state. A watchdog force-clears a Codex turn only after a configurable silence window, emits a visible forced-completion marker, and lets Claude send again.
- Codex exposes `idle`, `busy`, `stale`, and `offline` state. Watchdogs force-clear a Codex turn after either a configurable silence window or a configurable per-turn wall-clock budget, emit visible markers, and let Claude send again.
- Claude exposes `idle`, `expected`, `stale`, and `offline` state. Claude-owned lanes become stale after a configurable response timeout.
- A new Claude frontend does not blindly replace a live session. The daemon probes the incumbent frontend first; if it responds, the newcomer is rejected, and if it does not, the stale frontend is evicted with close code `4002`.

Expand Down Expand Up @@ -911,8 +912,11 @@ The exact runtime state path can be changed with `CONTEXTRELAY_STATE_DIR`. Norma
| `CONTEXTRELAY_CLAUDE_PROBE_TIMEOUT_MS` | `3000` | How long the daemon waits for an attached Claude frontend to answer a liveness probe before evicting it as stale. Set to `0` to disable probe eviction and keep the older reject-only behavior. |
| `CONTEXTRELAY_CLAUDE_RESPONSE_TIMEOUT_MS` | `300000` | How long a Claude-owned active task lane can remain unanswered before the task board marks it stale. |
| `CONTEXTRELAY_CODEX_TURN_IDLE_TIMEOUT_MS` | `300000` | Silence window before a stuck Codex turn is force-cleared and reported as a forced completion. |
| `CONTEXTRELAY_TURN_MAX_MS` | `300000` | Wall-clock budget for a single Codex turn before that turn is cleared from the busy set and reported as a turn watchdog event. Set to `0` to disable this guard. |
| `CONTEXTRELAY_MAX_DEPTH` | `3` | Maximum relay recursion depth. |
| `CONTEXTRELAY_BACKUP_THROTTLE_MS` | `60000` | Minimum delay between backup starts for the same target. |
| `CONTEXTRELAY_BACKUP_KILL_GRACE_MS` | `2000` | Grace period between backup timeout SIGTERM and SIGKILL escalation. |
| `CONTEXTRELAY_DAEMON_SHUTDOWN_STEP_TIMEOUT_MS` | `1500` | Per-step deadline for daemon shutdown cleanup before recording the step as timed out and continuing shutdown. |
| `CONTEXTRELAY_MAX_CONTROL_MESSAGE_BYTES` | `1000000` | Maximum accepted control WebSocket message size. |
| `CONTEXTRELAY_MAX_CONTROL_MESSAGES_PER_MINUTE` | `120` | Per-control-connection rate limit. |
| `CONTEXTRELAY_DAEMON_ENTRY` | bundled daemon | Plugin daemon entry. Overrides require `CONTEXTRELAY_ALLOW_DAEMON_ENTRY_OVERRIDE=1`. |
Expand Down
3 changes: 3 additions & 0 deletions dist/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,9 @@ function formatRuntimeEvent(event) {
event.path ? `path: ${event.path}` : undefined,
event.method ? `method: ${event.method}` : undefined,
typeof event.exitCode === "number" ? `exit_code: ${event.exitCode}` : undefined,
typeof event.durationMs === "number" ? `duration_ms: ${event.durationMs}` : undefined,
event.requestId ? `request_id: ${event.requestId}` : undefined,
event.backupTarget ? `backup_target: ${event.backupTarget}` : undefined,
event.detail
].filter(Boolean);
return details.join(`
Expand Down
Loading