fix(repair): stop stalled GitHub CLI requests blocking workers - #1302
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 31, 2026, 3:23 AM ET / 07:23 UTC. ClawSweeper reviewWhat this changesThe PR gives repair-lane GitHub CLI calls native per-command deadlines, honors per-call timeout environments, and adds focused regression coverage and documentation. Regression provenancePossible regression — probable (reviewed change; reproduction). No predecessor PR is attributed. Merge readinessThe prior per-call environment finding is resolved: all three shared helpers now derive their deadline from the same merged environment passed to the child process. The patch is correct and has strong controlled real-process proof; it remains open for normal maintainer landing review. Priority: P2 Review scores
Verification
How this fits togetherRepair workers use shared GitHub CLI helpers to query and update GitHub during bounded repair jobs. These helpers combine worker-provided environment settings, invoke the CLI, and return either output or native process failure details to the calling worker. flowchart LR
A[Repair worker] --> B[Per-call settings]
B --> C[GitHub CLI helpers]
C --> D[Deadline selection]
D --> E[GitHub CLI process]
E --> F[Output or timeout error]
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Land the bounded-helper behavior with the documented environment override retained for legitimately long GitHub CLI operations. Do we have a high-confidence way to reproduce the issue? Yes. The supplied controlled proof exercises the compiled helpers with real GitHub CLI requests against a local HTTP fixture, and current source confirms the timeout path used by each helper. Is this the best way to solve the issue? Yes. Passing Node's native timeout through the existing helper boundary is the narrowest solution, and deriving it from the merged child environment resolves the prior override bug without adding a separate process supervisor. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 1b9086615d89. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
Use the child environment for timeout selection and preserve native process failure semantics. Keep fractional explicit budgets positive after rounding. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
fbde940 to
acb5b36
Compare
|
@clawsweeper re-review The per-call environment finding is fixed: timeout selection now uses the same merged environment as the child. The updated PR body includes a real GitHub CLI before/after proof for that exact failure and both environment settings, plus normal-output and HTTP-error controls. The exact candidate passed the full check (4,151 passed, eight skipped) and both required Codex reviews were clean at the P0 scope. Hosted CI is running on the updated head. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Landed as 6224135. Thanks @SebTardif; contributor authorship is preserved. The per-call environment finding is resolved, and the documented two-minute default with per-call/environment overrides is accepted. Validation on secretless AWS Crabbox After merging, I pulled clean The original proposal's environment case stayed pending at the 31.5-second watchdog; unmodified main also ignored a short explicit budget. The first candidate proof attempt used the wrong Node error field for its HTTP-error assertion; the driver was corrected to read This is controlled HTTP failure injection using the real CLI and synthetic auth, not a live GitHub outage. It retains Node's native SIGTERM behavior and does not claim Windows process-tree coverage or a total retry-loop deadline. The isolated checkout ended clean on |
What Problem This Solves
Fixes stalled GitHub CLI requests in the shared repair helpers. These calls previously had no application deadline, and the original proposal ignored timeout settings supplied through the existing per-call
envoption.Why This Change Was Made
ghText,ghTextAsync, andghSpawnnow pass a native timeout to Node using the same merged environment supplied to their child process. A positive explicittimeoutMswins; otherwise the GitHub-specific environment setting takes precedence over the network fallback, with a two-minute default and 30-second minimum for configured values. A fractional positive explicit value is clamped to one millisecond so rounding cannot disable the deadline.This resolves the current review's
options.envfinding without adding another environment merge or process supervisor. Native error/result shapes and existing mutation-ledger handling remain in place. The synchronous shared helper was added without a timeout in 62dd779eb1, verified against its raw parent8e77181d04da619f26005d8c7299e0b9b2aeb3c4.User Impact
A stalled ordinary
ghprocess is terminated at its selected deadline instead of holding the repair worker open. Per-call worker settings now take effect. Healthy commands preserve stdout, and ordinary command failures remain failures.The deadline applies to each command attempt. Longer legitimate calls may require a larger configured budget. This does not bound the entire retry loop or add process-tree supervision; it retains Node's normal SIGTERM behavior.
OpenClaw Bay Impact
Unaffected: this changes worker-side process execution, not Bay's observer-only surface or any queue/status data shape.
Documentation Impact
Updated the active
docs/repair/README.mdreference with the shared-helper default, environment floor, and per-call precedence. Added a changelog entry with credit to @SebTardif.Evidence
The exact candidate tree
979970625147762dd98f60191387a8ce51724f2f(commitacb5b36df1e964e024fbe43462e11fe974599530) passedpnpm run check: 4,151 tests passed, eight skipped, and all 13 static checks passed. The focused suite passed six tests. Codex pre-commit review found no actionable P0 findings.The controlled proof uses the real
/usr/bin/ghagainst a local HTTP fixture, through the compiled production helpers. It supplies only synthetic auth in an isolated home and config directory. It does not replace child-process execution with a mock.Real Behavior Proof
cbx_500a9817fb0b, Linux, Node 24.18.1, GitHub CLI 2.46.0 from the image, pinned pnpm 11.10.0. No instance role, Tailscale, hydration, or live GitHub credentials.fbde9401b4148d95636ad895472f23b81677d49bstayed pending past 31.5 seconds with a per-call 30-second GH budget and an ambient 90-second value. The separate watchdog stopped that deliberately stuck driver.1b9086615d892ecc7c1fd4b681e8a1b1208dfa5cignored a 250 ms explicit budget and was still pending at the 1.2-second watchdog.ghText,ghTextAsync, andghSpawnterminated stalled real CLI requests in 254, 256, and 254 ms with an explicit 250 ms budget. Per-call GH and network settings terminated them in 30,012 and 30,011 ms despite ambient 90-second values. Every timed-out connection closed. Healthy requests after each helper returnedsynthetic-user, and a normal HTTP error retained native exit status 1.pnpm run build:all;node /tmp/clawsweeper-github-cli-proof.mjs run "$PWD" original-envon the original PR;baselineon the pinned main;candidateafter the patch;node --test test/repair/github-cli.test.ts;pnpm run check.The regression suite also checks merged-environment selection, the configured minimum, explicit precedence, invalid values, fractional rounding, and successful output. Environment-budget proof uses real 30-second timers without compression.
Standalone proof driver
Save as
/tmp/clawsweeper-github-cli-proof.mjsand run against a built checkout on Linux with/usr/bin/ghinstalled.