You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The generated native Claude Code daemon client currently collapses every negative response read() into exit code 11 with empty stderr. That makes receive timeout, EINTR, connection reset, and other I/O failures indistinguishable.
The client also ignores the result from setsockopt(..., SO_RCVTIMEO, ...), so it cannot prove that the configured receive timeout was armed.
POSIX specifies that a read() interrupted before transferring data returns -1 with errno=EINTR, and socket reads are equivalent to recv() with no flags. Linux permits either EAGAIN or EWOULDBLOCK for relevant socket conditions, so portable code must handle both.
Capture errno immediately after a failed native response read, before cleanup can overwrite it.
Emit a stable, sanitized diagnostic containing only operation/stage, numeric errno, and portable symbolic errno name.
Retry EINTR without allowing repeated interruptions to extend the configured overall response timeout indefinitely.
Treat EAGAIN, EWOULDBLOCK, ETIMEDOUT, and persistent socket/read errors as non-retryable terminal outcomes.
Check receive-timeout setup and fail visibly if the timeout cannot be armed.
Preserve nonzero, fail-closed native behavior and existing protocol-validation failures.
Add a test-only native syscall seam or equivalent deterministic mechanism; do not rely on scheduler timing to manufacture EINTR.
Out of scope:
changing latency thresholds;
changing .github/workflows/tests.yml;
uploading benchmark artifacts;
choosing a dedicated or multi-run performance runner;
deduplicating push and pull-request runs; and
changing branch protection.
Acceptance criteria
A failed native response read reports numeric and symbolic errno.
Diagnostics never include request bodies, mission passports, tokens, tool arguments, socket paths, temporary paths, environment dumps, or other host-specific data.
A single injected EINTR is retried and a subsequent valid daemon response succeeds.
Repeated EINTR cannot extend the configured overall response budget without bound.
Receive timeout is not retried into success and remains a nonzero native outcome.
Persistent injected read errors fail immediately and retain their original errno.
Failure to configure SO_RCVTIMEO is visible and nonzero.
Existing malformed, truncated, and negative daemon-protocol responses remain rejected.
Existing native exit-code consumers retain an explicit, tested compatibility contract.
Generated C builds warning-clean with repository compiler flags on supported Linux and macOS test environments.
Targeted tests
Deterministic fault injection: EINTR once, then successful read.
Deterministic fault injection: repeated EINTR reaches the bounded terminal policy.
Deterministic fault injection: persistent EIO or equivalent terminal read error.
Ruff, pre-commit, check-local.sh --quick, and git diff --check.
A base-revision red proof should demonstrate that the new errno and retry assertions fail on unmodified dev.
Security and cost
This is a local Unix-socket correctness change. It requires no cloud credentials, Kubernetes workload, Docker image, external provider, or live model.
The diagnostic format must use an allowlisted field set rather than interpolating user-controlled strings. The implementation must not convert native transport failure into an allow result.
Runtime and CI cost should remain effectively unchanged; tests must use bounded deterministic injection rather than repeated timing loops.
Dependencies and overlap
Fresh decomposition audit used exact devdfe4905bccfa3189ab2ee97e0d8f206a711ec9d4.
Parent: #364
Problem
The generated native Claude Code daemon client currently collapses every negative response
read()into exit code 11 with empty stderr. That makes receive timeout,EINTR, connection reset, and other I/O failures indistinguishable.The client also ignores the result from
setsockopt(..., SO_RCVTIMEO, ...), so it cannot prove that the configured receive timeout was armed.POSIX specifies that a
read()interrupted before transferring data returns-1witherrno=EINTR, and socket reads are equivalent torecv()with no flags. Linux permits eitherEAGAINorEWOULDBLOCKfor relevant socket conditions, so portable code must handle both.Primary references, rechecked 2026-07-23:
read()read(2)read(2)Scope
In scope:
errnoimmediately after a failed native response read, before cleanup can overwrite it.EINTRwithout allowing repeated interruptions to extend the configured overall response timeout indefinitely.EAGAIN,EWOULDBLOCK,ETIMEDOUT, and persistent socket/read errors as non-retryable terminal outcomes.EINTR.Out of scope:
.github/workflows/tests.yml;Acceptance criteria
EINTRis retried and a subsequent valid daemon response succeeds.EINTRcannot extend the configured overall response budget without bound.SO_RCVTIMEOis visible and nonzero.Targeted tests
EINTRonce, then successful read.EINTRreaches the bounded terminal policy.EIOor equivalent terminal read error.check-local.sh --quick, andgit diff --check.A base-revision red proof should demonstrate that the new errno and retry assertions fail on unmodified
dev.Security and cost
This is a local Unix-socket correctness change. It requires no cloud credentials, Kubernetes workload, Docker image, external provider, or live model.
The diagnostic format must use an allowlisted field set rather than interpolating user-controlled strings. The implementation must not convert native transport failure into an allow result.
Runtime and CI cost should remain effectively unchanged; tests must use bounded deterministic injection rather than repeated timing loops.
Dependencies and overlap
devdfe4905bccfa3189ab2ee97e0d8f206a711ec9d4.devand parent CI: harden flaky latency benchmark before making it required #364.python/vibap/claude_code_daemon.pyor the proposed focused native-client test surface..github/workflows/tests.yml, which is concurrently touched by open Dependabot PRs ci(deps): bump actions/setup-python from 6.3.0 to 7.0.0 #358 and ci(deps): bump actions/setup-go from 6.5.0 to 7.0.0 #360.dev, open PRs, and worktrees before claiming the lane.