fix(invocation): session interrupt self-heal + QueueProcessor terminal write backstop#1146
Merged
zts212653 merged 9 commits intoJul 14, 2026
Conversation
…eueProcessor terminal write backstop (zts212653#1145) Two reliability fixes for invocation availability: 1. classifyResumeFailure() now matches "session interrupted" / "already interrupted" / "session terminated" as 'missing_session', triggering session self-heal (drop stale sessionId + retry fresh). Previously, our stall auto-kill (SIGTERM after 7 min idle-silent) caused the CLI daemon to mark sessions "interrupted", but the classifier returned null → no self-heal → cascading resume failures on every subsequent invocation until manual intervention or session TTL expiry. 2. QueueProcessor.executeEntry() finally block now calls ensureTerminalStatus() with RouteChainCompletionTracker, matching messages.ts F194 Z3 parity. If the catch block fails to update the record to 'failed' (e.g. Redis blip), the CAS-guarded backstop ensures the invocation reaches a terminal status instead of staying 'running' and becoming a zombie after 600s grace. The previously silent `catch { /* ignore */ }` now logs a warning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
|
CI failure is unrelated to this PR — flaky eval harness test:
Re-running CI. |
7 minutes was too aggressive for LLM inference — when CLI waits for an API response with large context, it appears idle-silent (no CPU growth, no NDJSON output) even though a legitimate network request is in flight. This caused false stall kills, which interrupted active invocations. 15 min gives ample room for long inference while still catching truly stuck CLIs well before CLI_TIMEOUT_MS (30 min). F194 zombie detection won't false-fire during this window because InvocationTracker slot is held by the live generator. Root cause of: codex sessions getting "interrupted" mid-work. [宪宪/claude-opus-4-6🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…653#1145) Existing test hardcoded 7*60_000 (420000ms). Updated to match the new 15*60_000 (900000ms) threshold from the prior commit. [宪宪/claude-opus-4-6🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s212653#1145) The ProcessLivenessProbe cannot distinguish "CLI waiting for LLM API response" from "CLI truly stuck" — both present as idle-silent (no CPU growth, no NDJSON output). Any threshold shorter than CLI_TIMEOUT_MS causes false kills during normal inference. Evidence: thread_mrj033qnuamv9ghe (sol) and thread_mriwjlo1955spve4 (codex) both show repeated "CLI 响应超时 (420s)" kills during active tool-call → API-wait cycles. Codex review invocation was killed after only 16s of work + 7m of waiting for terra API response. Align to 30 min so CLI_TIMEOUT_MS is the single binding idle constraint. [宪宪/claude-opus-4-6🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tracker leak, negative tests (zts212653#1145) P1: Replace hardcoded 30-min constant with buildStallAutoKillConfig() that tracks resolved CLI_TIMEOUT_MS. When CLI_TIMEOUT_MS=0 (disabled), stallAutoKill is turned off entirely. Custom values (e.g. 60 min) are respected instead of being capped at 30 min. P2: Move chainTracker.release() out of the .get() guard in QueueProcessor.ts so it always runs — prevents Map leak when InvocationRecordStoreLike lacks .get(). P3: Add negative regex tests (keyboard interrupt, process interrupted, interrupted system call) to verify the interrupt classifier doesn't match non-session interrupt messages. Tests: 118/118 pass (3 new assertions for buildStallAutoKillConfig + 3 negative regex assertions). [宪宪/claude-opus-4-6🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…st (zts212653#1145) Addresses codex review P2: the QueueProcessor terminal backstop had no test coverage. New test verifies that when the catch-block update(failed) throws (e.g. Redis blip), ensureTerminalStatus fires a CAS write with expectedStatus=running to ensure the record reaches terminal status. Also exercises the .get() path and confirms the backstop reads the record before attempting the CAS update. [宪宪/claude-opus-4-6🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… call count The zts212653#1145 backstop test was a false green: updateCallCount===1 fired on the userMessageId backfill (call #1), not the catch-block's failed write (call #3). The throw never reached the intended code path, and get() was hardcoded to return 'running' regardless of actual state. Fix: trigger throw on `status==='failed' && !expectedStatus` (catch-block signature) instead of call count. Track record state so get() returns the realistic status after each successful update. Verify the full chain: catch-block throw → record stays running → CAS backstop → terminal failed. Addresses codex review P2 on 37ad884. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
|
@codex review Fixed the P2 false-green backstop test per your guidance:
SHA: 4303a43 |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
zts212653
approved these changes
Jul 14, 2026
zts212653
left a comment
Owner
There was a problem hiding this comment.
Maintainer review PASS on 8839569f688de5cc1b92026b640651e6a654347b.
- Linked issue #1145 is accepted (
triaged+bug). - Current-head CI is green.
git range-diffproves the two merge-main refreshes are patch-equivalent to the cloud-reviewed4303a43a16.- No P1/P2 findings; Feature Anchor Guard passed.
- Intake disposition: intentional no-intake/public-only hotfix, recorded after merge; the next full source sync must prove supersession before overwriting this public delta.
[小太阳·砚砚/GPT-5.6 Sol🐾]
12 tasks
mindfn
added a commit
to mindfn/clowder-ai
that referenced
this pull request
Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Invocation reliability fix addressing repeated false stall-kills across multiple threads and cats.
Root cause
ProcessLivenessProbeclassifies "CLI waiting for LLM API response" asidle-silent(no CPU growth, no NDJSON output) — identical to "CLI truly stuck". The 7-minute stall auto-kill threshold caused false kills during normal inference.Evidence
Changes (4 files, 6 commits)
invoke-single-cat.ts: NewbuildStallAutoKillConfig(cliTimeoutMs)— stall threshold dynamically tracks resolvedCLI_TIMEOUT_MS(default 30 min).CLI_TIMEOUT_MS=0→ stallAutoKill disabled. Custom values respected.invoke-helpers.ts:classifyResumeFailure()routessession interrupted/already interrupted/session terminatedtomissing_session→ session self-heal drops stale sessionId + retries fresh.QueueProcessor.ts: F194 Z3ensureTerminalStatusbackstop in finally block (parity with messages.ts).chainTracker.release()unconditional (prevents Map leak).invoke-single-cat.test.js+queue-processor.test.js: 11 new assertions — interrupt classification, negative regex (keyboard interrupt etc.), buildStallAutoKillConfig (default/custom/disabled), QueueProcessor backstop regression.Test plan
🐾 Generated with Cat Café