fix(daemon): skip pre-existing gateway listeners as schtask launch evidence (#91144)#91198
fix(daemon): skip pre-existing gateway listeners as schtask launch evidence (#91144)#91198openperf wants to merge 1 commit into
Conversation
|
Codex review: needs changes before merge. Reviewed June 7, 2026, 9:32 PM ET / 01:32 UTC. Summary PR surface: Source +39, Tests +56. Total +95 across 2 files. Reproducibility: yes. source-level reproduction is high confidence: current main lets readScheduledTaskRuntime report running from a verified listener before fallback polling, and the linked issue reports the same status followed by ECONNREFUSED after the foreground gateway closes. I did not run a live Windows Scheduled Task scenario in this read-only review. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Keep termination limited to verified gateway PIDs, but make launch evidence ignore all listeners that existed before schtasks /Run or only trust verified post-launch OpenClaw gateway evidence, with a regression for an unverified pre-bound port listener. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high confidence: current main lets readScheduledTaskRuntime report running from a verified listener before fallback polling, and the linked issue reports the same status followed by ECONNREFUSED after the foreground gateway closes. I did not run a live Windows Scheduled Task scenario in this read-only review. Is this the best way to solve the issue? No. The fix direction is right, but the best version separates killable verified gateway cleanup from launch-evidence filtering so unverified pre-existing port owners cannot be mistaken for a task start. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 5c5391836b1e. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +39, Tests +56. Total +95 across 2 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
ab9b8ef to
7cd0d5d
Compare
7cd0d5d to
ef5ce9e
Compare
ef5ce9e to
a4db3ae
Compare
a4db3ae to
66b3fb7
Compare
Summary
openclaw gatewayis already running on the task port,openclaw gateway install/start/restartregisters the Scheduled Task but the gateway does not persist after the foreground window is closed. The reporter saw"Verified gateway listener detected on port 18789 even though schtasks did not report a running task"in status output, thenECONNREFUSED 127.0.0.1:18789after closing the foreground window ([Bug]: Windows native CLI gateway Scheduled Task does not stay running; foreground window worksWindows native CLI gateway Scheduled Task does not stay running; foreground window works #91144).shouldFallbackScheduledTaskLaunchpolled task state viareadScheduledTaskRuntime, which callsresolveListenerBackedScheduledTaskRuntimeto enrich non-running schtasks state. When a foreground gateway occupies the task port,resolveListenerBackedScheduledTaskRuntimefinds its listener PID and returnsstatus: "running"— soreadLaunchObservationimmediately returnsstate: "running"andshouldFallbackScheduledTaskLaunchreturnsfalse(no fallback needed) before schtasks can even report the task state. The same pre-existing PID also passed thehasLaunchEvidenceport check at the end of the polling timeout window (src/daemon/schtasks.ts).runScheduledTaskOrThrowsnapshots any listener PIDs on the task port before callingschtasks /Run.shouldFallbackScheduledTaskLaunchreceivestaskPortandpreExistingListenerPids;readLaunchObservationreads raw schtasks state directly (bypassingresolveListenerBackedScheduledTaskRuntime) and counts only PIDs that appeared after the task was launched as task-start evidence;hasLaunchEvidencefilters the same pre-existing set.src/daemon/schtasks.ts—runScheduledTaskOrThrowcaptures pre-existing listener PIDs;shouldFallbackScheduledTaskLaunchtakes newtaskPort/preExistingListenerPidsparams;readLaunchObservationuses direct schtasks queries instead ofreadScheduledTaskRuntime;hasLaunchEvidencefilters pre-existing PIDssrc/daemon/schtasks.startup-fallback.test.ts— one new regression test for the foreground-gateway-listener-as-evidence scenario!shouldManageGatewayListenerPort) — no changes to node task evidence logicreadScheduledTaskRuntimeandresolveListenerBackedScheduledTaskRuntime— still used for runtime status reporting, unchangedReproduction
openclaw gateway— it binds port 18789openclaw gateway install(orstartorrestart) — schtasks registers and attempts to run the Scheduled Taskschtasksreports the task asnot-yet-runreadLaunchObservationcallsreadScheduledTaskRuntime→resolveListenerBackedScheduledTaskRuntimesees the foreground gateway on port 18789 → returnsstatus: "running"immediately →shouldFallbackScheduledTaskLaunchreturnsfalsewith no fallback launched; closing the foreground window leaves no persistent gateway (ECONNREFUSED 127.0.0.1:18789)schtasks /Run;readLaunchObservationandhasLaunchEvidencefilter it out; after the polling timeout finds no new listeners, the fallback launcher is spawned; the managed gateway persists after the foreground window closesReal behavior proof
Behavior addressed (#91144): When a foreground
openclaw gatewayoccupies the task port beforeschtasks /Run, the pre-existing listener PID was falsely accepted as proof the Scheduled Task started, suppressing the Startup-style fallback launcher. Gateway did not persist after the foreground window closed.Real environment tested (Linux, Node 22.19 — Vitest against production
shouldFallbackScheduledTaskLaunchandhasLaunchEvidencewith mocked schtasks calls and port listener detection):node scripts/run-vitest.mjs src/daemon/schtasks.startup-fallback.test.ts src/daemon/schtasks.test.tsExact steps or command run after this patch:
node scripts/run-vitest.mjs src/daemon/schtasks.startup-fallback.test.ts src/daemon/schtasks.test.tsEvidence after fix (Vitest output, 57 tests across startup-fallback + schtasks suites):
Observed result after fix: All 57 tests pass — including the new regression test "falls back when a foreground gateway on the task port is the only listener after /Run (#91144)" — and all 27 pre-existing startup-fallback scenarios remain green.
What was not tested: Live Windows run confirming the patched path end-to-end (the
clawsweeper:source-reprolabel on #91144 notes a native Windows run is needed to capture the exact Task Scheduler Last Run Result and confirm behavior with a real Scheduled Task registration).Repro confirmation: The new regression test fails on
mainwithExpected "spawn" to have been called(the foreground PID suppresses the fallback before any polling completes) and passes after this patch. Confirmed by temporarily restoringsrc/daemon/schtasks.tstoorigin/mainwith the test file in place.Risk / Mitigation
readLaunchObservationnow issues two schtasks calls directly instead of delegating toreadScheduledTaskRuntime. Mitigation: The two calls (/Queryfor availability +/Query /TN ... /V /FO LISTfor task state) are identical to whatreadScheduledTaskRuntimemakes internally; all 57 existing tests pass; thereadScheduledTaskRuntimecode path for runtime status reporting is unchanged.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Fixes #91144