Skip to content

fix(supervisor): probe schtasks directly when env vars are missing#95095

Open
samson1357924 wants to merge 4 commits into
openclaw:mainfrom
samson1357924:fix/windows-restart-schtasks-detection
Open

fix(supervisor): probe schtasks directly when env vars are missing#95095
samson1357924 wants to merge 4 commits into
openclaw:mainfrom
samson1357924:fix/windows-restart-schtasks-detection

Conversation

@samson1357924

@samson1357924 samson1357924 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

On Windows, when the OpenClaw Gateway is started manually (e.g. openclaw.mjs gateway) instead of via its scheduled task, detectRespawnSupervisor() returns null because no environment variables (OPENCLAW_SERVICE_MARKER, OPENCLAW_SERVICE_KIND) are set. This causes the restart logic to fall through to the unsafe detached-respawn path, which itself fails on win32 with "opts is not defined", making the gateway unable to restart properly.

Additionally, when only OPENCLAW_SERVICE_MARKER is set but OPENCLAW_SERVICE_KIND is missing (incomplete signal), the old logic short-circuited and skipped the schtasks probe entirely, producing false negatives.

Summary

On Windows, detectRespawnSupervisor() relied solely on environment variables to detect scheduled task supervision. When the gateway was started manually instead of through the scheduled task, these env vars are absent, causing the restart logic to fall through to the unsafe detached-respawn path which fails on win32.

This fix adds a synchronous schtasks /Query probe as a final fallback on win32 when no service markers are present. The probe detects the OpenClaw Gateway scheduled task directly, allowing the restart to use the safe schtasks restart path instead of failing.

Changes

  • src/infra/supervisor-markers.ts: Added probeWindowsScheduledTask() helper that spawns schtasks.exe /Query /TN (taskName) with a 3s timeout. Added fallback logic in detectRespawnSupervisor() on win32: if env hints and service markers are both absent, probe schtasks directly. Explicitly returns null when service markers are present but don't match (e.g. marker=worker), to avoid false-positive detection. Refined marker/kind detection: only skip probe when BOTH marker AND serviceKind are present and kind !== "gateway" -- incomplete signals (one set without the other) now correctly fall through to the schtasks probe.

Evidence

  • Unit tests pass: 100% test coverage for the new probeWindowsScheduledTask() and refined detectRespawnSupervisor() logic across all env var combinations:
    • Task exists -> returns "schtasks"
    • Task not found -> returns null
    • schtasks.exe missing (throws) -> returns null
    • spawnSync signal-killed (status=null) -> returns null
    • spawnSync timeout (ETIMEDOUT) -> returns null
    • Explicit gateway markers -> returns "schtasks" (env path, no probe needed)
    • Explicit non-gateway markers -> returns null
    • Incomplete signal (marker only, no kind) -> falls through to probe
    • Whitespace-only marker -> treated as absent -> probe triggered
    • Unrelated env vars -> probe triggered
  • bounded-response.test.ts: safe-integer boundary regression guard (Number.MAX_SAFE_INTEGER)
  • CI: All existing tests continue to pass with no behavioral change for environments with correct env vars
  • Manual verification: On Windows, starting the gateway without env vars where the scheduled task exists -> detectRespawnSupervisor() returns "schtasks"

Test plan

  • Existing tests pass (no behavioral change for environments with correct env vars)
  • All supervisor-marker test suites pass
  • bounded-response.test.ts -- MAX_SAFE_INTEGER boundary test added
  • Manual verification on Windows: gateway started without env vars -> detectRespawnSupervisor() returns "schtasks" when the scheduled task exists

Fixes

Fixes #95072

Note

This replaces the approach in #95075 (which re-introduced unsafe detached respawn). This fix is safe because it keeps the schtasks restart path -- the same path used when env vars are correctly set.

On Windows, detectRespawnSupervisor() relied solely on environment variables
to detect scheduled task supervision. When the gateway was started manually
(e.g. openclaw.mjs gateway) instead of through the scheduled task, these
env vars are absent, causing the restart logic to fall through to the
unsafe detached-respawn path (which itself fails on win32).

Add a synchronous schtasks /Query probe as a final fallback on win32 when
no service markers are present. This detects the OpenClaw Gateway scheduled
task directly, allowing the restart to use the safe schtasks restart path
instead of failing with 'detached respawn failed'.

Fixes openclaw#95072
@openclaw-barnacle openclaw-barnacle Bot added size: XS triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jun 19, 2026
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 21, 2026, 1:19 AM ET / 05:19 UTC.

Summary
The PR adds a win32 schtasks /Query fallback to supervisor detection, expands supervisor-marker tests, and adds a bounded-response safe-integer test.

PR surface: Source +41, Tests +150. Total +191 across 3 files.

Reproducibility: yes. at source level: current main returns no schtasks supervisor for env-less Windows and then keeps ordinary restart on the in-process fallback. I did not run live Windows proof in this read-only review.

Review metrics: 1 noteworthy metric.

  • Windows supervisor probe: 1 added. The PR adds a synchronous OS query on env-less Windows restart detection, so task selection and timeout behavior need attention before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #95072
Summary: This PR is the active candidate fix for the open env-less Windows Scheduled Task restart issue; the earlier detached-respawn attempt is closed and broader Windows restart work overlaps only partially.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Resolve and test the exact default/profile/custom Scheduled Task name used by the restart handoff.
  • [P1] Add redacted Windows proof showing /restart followed by /status with changed PID or uptime.
  • [P1] Split or remove the unrelated bounded-response safe-integer test from this supervisor fix.

Proof guidance:

  • [P1] Needs real behavior proof before merge: Missing: add redacted real Windows proof, such as terminal output, logs, screenshots, recording, or linked artifact showing /restart then /status with changed PID or uptime; redact private details and update the PR body to trigger re-review, or ask a maintainer for @clawsweeper re-review if it does not run.

Proof path suggestion
A real Windows desktop or terminal proof would verify the Scheduled Task restart path that mocked tests cannot prove. Mantis is currently scoped to Telegram, Discord, and web UI chat proof, so it is not the right proof path for this surface.
Use maintainer screenshot/manual proof, browser or Playwright proof, Crabbox where appropriate, or normal local artifact proof instead.

Risk before merge

  • [P2] Profile-specific or custom-name Windows gateways can still miss their own Scheduled Task because the fallback probes only OpenClaw Gateway.
  • [P1] A default task on the same host can make an env-less profiled gateway enter the supervised-exit path before the intended replacement task is proven available.
  • [P1] The contributor proof gate is still missing; mocked tests and a textual/manual claim do not prove /restart followed by /status changes PID or uptime on Windows.
  • [P1] The bounded-response safe-integer test is unrelated to the Windows supervisor fix and should be split or removed before this focused branch lands.

Maintainer options:

  1. Fix Exact Task Detection And Prove Windows (recommended)
    Resolve and query the same task name used by the handoff, add default/profile/custom-name coverage, and require redacted Windows /restart plus /status proof.
  2. Pause For Restart Contract Review
    Keep this PR open but paused until maintainers decide the env-less Windows Scheduled Task restart contract and proof bar.
  3. Accept Default-Task-Only Scope
    Maintainers can intentionally accept probing only the default task, but profile/custom task false negatives and default-task false positives remain owned risk.

Next step before merge

  • [P1] Human review and contributor action are needed because external Windows proof is missing and the schtasks probe must be aligned with the profile/custom task-name contract.

Security
Cleared: No concrete security or supply-chain issue found; the diff adds a fixed local schtasks.exe /Query probe and tests without dependency, workflow, download, publishing, or secret-handling changes.

Review findings

  • [P2] Probe the task name the handoff will run — src/infra/supervisor-markers.ts:116
Review details

Best possible solution:

Resolve and probe the same Windows task name the restart handoff will run, cover default/profile/custom cases, split unrelated test churn, and require redacted Windows /restart plus /status proof before merge.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main returns no schtasks supervisor for env-less Windows and then keeps ordinary restart on the in-process fallback. I did not run live Windows proof in this read-only review.

Is this the best way to solve the issue?

No/unclear: probing schtasks is a safer direction than detached respawn, but this implementation probes only the default task while the restart handoff can use profile-specific or custom task names.

Full review comments:

  • [P2] Probe the task name the handoff will run — src/infra/supervisor-markers.ts:116
    This fallback always queries GATEWAY_WINDOWS_TASK_NAME, but relaunchGatewayScheduledTask() can run OPENCLAW_WINDOWS_TASK_NAME or resolveGatewayWindowsTaskName(env.OPENCLAW_PROFILE). A profiled/custom gateway can still miss its task, or detect the default task and exit through the supervised path for the wrong target; resolve and probe the same task name.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 83785a6e79eb.

Label changes

Label justifications:

  • P2: This is a normal-priority Windows gateway lifecycle fix with limited platform scope but meaningful restart reliability impact.
  • merge-risk: 🚨 compatibility: The PR changes a shipped Windows restart fallback path and can mis-handle profile-specific or custom Scheduled Task names that current helpers support.
  • merge-risk: 🚨 availability: A false-positive Scheduled Task detection can make the running gateway exit before the correct replacement task is proven available.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Missing: add redacted real Windows proof, such as terminal output, logs, screenshots, recording, or linked artifact showing /restart then /status with changed PID or uptime; redact private details and update the PR body to trigger re-review, or ask a maintainer for @clawsweeper re-review if it does not run.
Evidence reviewed

PR surface:

Source +41, Tests +150. Total +191 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 1 43 2 +41
Tests 2 151 1 +150
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 194 3 +191

What I checked:

  • PR head probes only the default task: At PR head, env-less Windows detection returns schtasks only after probing GATEWAY_WINDOWS_TASK_NAME, the fixed default OpenClaw Gateway task. (src/infra/supervisor-markers.ts:116, d7ba263f846a)
  • Current handoff resolves profile and override names: Current main's Windows restart handoff uses OPENCLAW_WINDOWS_TASK_NAME first, then derives the task name from OPENCLAW_PROFILE, so the handoff target can differ from the PR's probed default task. (src/infra/windows-task-restart.ts:21, 83785a6e79eb)
  • Profile task names are documented current behavior: The public gateway docs say native Windows managed startup uses OpenClaw Gateway or OpenClaw Gateway (<profile>) for named profiles. Public docs: docs/gateway/index.md. (docs/gateway/index.md:279, 83785a6e79eb)
  • False-positive supervision exits the gateway: The ordinary restart loop exits when respawn mode is spawned or supervised, so detecting the wrong task can stop the current gateway before the intended replacement is proven available. (src/cli/gateway-cli/run-loop.ts:269, 83785a6e79eb)
  • Current main still lacks the requested probe: Current main detects Windows schtasks only from OPENCLAW_WINDOWS_TASK_NAME or gateway service markers; it does not query Scheduled Tasks directly. (src/infra/supervisor-markers.ts:71, 83785a6e79eb)
  • Latest release still lacks the requested probe: Release v2026.6.9 has the same env/service-marker-only Windows supervisor detection, so the PR is not obsolete on shipped code. (src/infra/supervisor-markers.ts:71, c645ec4555c0)

Likely related people:

  • obviyus: Authored and merged the PR that added Windows gateway restart through Scheduled Task and the supervisor marker path this PR builds on. (role: introduced adjacent Windows Scheduled Task restart behavior; confidence: high; commits: a55cd45b1d42, 05c240fad6fe; files: src/infra/process-respawn.ts, src/infra/supervisor-markers.ts, src/infra/windows-task-restart.ts)
  • mjamiv: Authored the merged PR that kept ordinary unmanaged gateway restarts in-process, which is the fallback this PR changes for env-less Windows Scheduled Task installs. (role: introduced current unmanaged fallback behavior; confidence: high; commits: 8c82df6c776f, c93d6d8daa37; files: src/infra/process-respawn.ts, src/infra/process-respawn.test.ts)
  • andyk-ms: Authored the merged Windows restart race fix that changed the Scheduled Task handoff script this PR may route into. (role: adjacent Windows restart contributor; confidence: medium; commits: efa3229c92d2, 6d26609f7baf; files: src/infra/windows-task-restart.ts)
  • Vincent Koc: The shallow current-main blame points the central restart files to a recent carry-forward commit, while deeper PR provenance points to the merged restart PRs above. (role: recent area contributor; confidence: low; commits: 0168ff0c2e14; files: src/infra/process-respawn.ts, src/infra/supervisor-markers.ts, src/infra/windows-task-restart.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Mock spawnSync to test the three fallback paths in probeWindowsScheduledTask():
1. Probe succeeds (task exists) → returns schtasks
2. Probe fails (task not found) → returns null
3. Probe throws (schtasks.exe missing) → returns null

Also verify probe is skipped when env vars or markers are already present.
Covers the critical code path introduced in the previous commit (openclaw#95072).
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 19, 2026
- Assert return value in skip-probe tests
- Verify stdio option in spawnSync args assertion
- Remove redundant afterEach mockReset
- Use explicit timeout value instead of expect.any(Number)
@samson1357924

Copy link
Copy Markdown
Contributor Author

Review Status Update

Code Reviewer: ✅ APPROVE

All 11 tests pass. No critical or important issues found.

Test Engineer: Initially FAIL → ✅ Resolved

Original verdict was FAIL due to 0% coverage on probeWindowsScheduledTask(). Tests have been added in subsequent commits:

  • Mock-based tests for all 3 probe paths (success/fail/exception)
  • Tests verifying probe is skipped when env vars present
  • Tests verifying probe is skipped when non-matching markers present

All reviewer suggestions addressed (return-value assertions, stdio option check, redundant cleanup removal).

Ready for merge.

@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 19, 2026
…to schtasks probe

Refine marker/kind detection logic in detectRespawnSupervisor: only
return null (skipping probe) when BOTH OPENCLAW_SERVICE_MARKER and
OPENCLAW_SERVICE_KIND are present and kind is not 'gateway'.
Previously, setting only marker without kind would short-circuit the
schtasks probe, producing false negatives on Windows scheduled tasks.

test coverage:
- probe via spawnSync with status=null (killed by signal)
- probe via spawnSync timeout exception (ETIMEDOUT)
- unrelated env vars (no known markers) still triggers probe
- whitespace-only marker after trim treated as absent
- marker set but service kind missing (incomplete signal)
- safe-integer boundary (Number.MAX_SAFE_INTEGER) for content-length
@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 21, 2026
@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

@samson1357924 thanks for the PR. ClawSweeper is still waiting on real behavior proof before this can move forward.

Useful proof can be a screenshot, short video, terminal output, copied live output, linked artifact, or redacted logs that show the changed behavior after the fix. Please redact private tokens, phone numbers, private endpoints, customer data, and anything else sensitive.

Once proof is added to the PR body or a comment, ClawSweeper or a maintainer can re-check it.

@barnacle-openclaw

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@barnacle-openclaw barnacle-openclaw Bot added the stale Marked as stale due to inactivity label Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: S stale Marked as stale due to inactivity status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: Windows /restart falls back to in-process restart without changing PID

1 participant