Skip to content

Commit edd7623

Browse files
authored
fix(daemon): keep duplicate Windows gateway tasks visible
Normalize Windows schtasks default gateway names without hiding similarly prefixed duplicate tasks. Verified with focused daemon tests, type proof, autoreview, and clean CI.
1 parent d6b3950 commit edd7623

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

src/daemon/inspect.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,12 @@ describe("findExtraGatewayServices (win32)", () => {
356356
});
357357

358358
it("collects only non-openclaw marker tasks from schtasks output", async () => {
359+
// Real schtasks /Query /FO LIST /V output prefixes root-folder task
360+
// names with a backslash (e.g. TaskName:\OpenClaw Gateway).
359361
execSchtasksMock.mockResolvedValueOnce({
360362
code: 0,
361363
stdout: [
362-
"TaskName: OpenClaw Gateway",
364+
"TaskName:\\OpenClaw Gateway",
363365
"Task To Run: C:\\Program Files\\OpenClaw\\openclaw.exe gateway run",
364366
"",
365367
"TaskName: Clawdbot Legacy",
@@ -373,6 +375,8 @@ describe("findExtraGatewayServices (win32)", () => {
373375
});
374376

375377
const result = await findExtraGatewayServices({}, { deep: true });
378+
// The \OpenClaw Gateway task is the live launcher — it must be skipped.
379+
// Only the unrelated clawdbot task should be flagged.
376380
expect(result).toEqual([
377381
{
378382
platform: "win32",
@@ -384,4 +388,35 @@ describe("findExtraGatewayServices (win32)", () => {
384388
},
385389
]);
386390
});
391+
392+
it("reports duplicate root tasks that only share the gateway task prefix", async () => {
393+
execSchtasksMock.mockResolvedValueOnce({
394+
code: 0,
395+
stdout: [
396+
"TaskName:\\OpenClaw Gateway",
397+
"Task To Run: C:\\Program Files\\OpenClaw\\openclaw.exe gateway run",
398+
"",
399+
"TaskName:\\OpenClaw Gateway (dev)",
400+
"Task To Run: C:\\Program Files\\OpenClaw\\openclaw.exe gateway run --profile dev",
401+
"",
402+
"TaskName:\\OpenClaw Gateway Backup",
403+
"Task To Run: C:\\Program Files\\OpenClaw\\openclaw.exe gateway run",
404+
"",
405+
].join("\n"),
406+
stderr: "",
407+
});
408+
409+
const result = await findExtraGatewayServices({}, { deep: true });
410+
expect(result).toEqual([
411+
{
412+
platform: "win32",
413+
label: "\\OpenClaw Gateway Backup",
414+
detail:
415+
"task: \\OpenClaw Gateway Backup, run: C:\\Program Files\\OpenClaw\\openclaw.exe gateway run",
416+
scope: "system",
417+
marker: "openclaw",
418+
legacy: false,
419+
},
420+
]);
421+
});
387422
});

src/daemon/inspect.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,13 @@ function isOpenClawGatewayTaskName(name: string): boolean {
203203
if (!normalized) {
204204
return false;
205205
}
206+
// Windows schtasks /Query returns task names prefixed with \ (e.g.
207+
// \OpenClaw Gateway for root-folder tasks). Strip the leading
208+
// backslash so the configured name matches correctly and the live
209+
// gateway task is not misidentified as an extra gateway service.
210+
const stripped = normalized.replace(/^\\+/, "");
206211
const defaultName = normalizeLowercaseStringOrEmpty(resolveGatewayWindowsTaskName());
207-
return normalized === defaultName || normalized.startsWith("openclaw gateway");
212+
return stripped === defaultName || /^openclaw gateway \(.+\)$/.test(stripped);
208213
}
209214

210215
function tryExtractPlistLabel(contents: string): string | null {

0 commit comments

Comments
 (0)