




















@@ -28,6 +28,7 @@ const loadGatewayTlsRuntime = vi.fn(async (_cfg?: unknown) => ({
2828fingerprintSha256: "sha256:11:22:33:44",
2929}));
3030const findExtraGatewayServices = vi.fn(async (_env?: unknown, _opts?: unknown) => []);
31+const findStaleOpenClawUpdateLaunchdJobs = vi.fn(async () => []);
3132const inspectPortUsage = vi.fn(async (port: number) => ({
3233 port,
3334status: "free" as const,
@@ -139,6 +140,10 @@ vi.mock("../../daemon/inspect.js", () => ({
139140findExtraGatewayServices: (env: unknown, opts?: unknown) => findExtraGatewayServices(env, opts),
140141}));
141142143+vi.mock("../../daemon/launchd.js", () => ({
144+findStaleOpenClawUpdateLaunchdJobs: () => findStaleOpenClawUpdateLaunchdJobs(),
145+}));
146+142147vi.mock("../../daemon/service-audit.js", () => ({
143148auditGatewayServiceConfig: (opts: unknown) => auditGatewayServiceConfig(opts),
144149}));
@@ -210,6 +215,8 @@ describe("gatherDaemonStatus", () => {
210215delete process.env.DAEMON_GATEWAY_PASSWORD;
211216callGatewayStatusProbe.mockClear();
212217createConfigIOCalls.mockClear();
218+findStaleOpenClawUpdateLaunchdJobs.mockReset();
219+findStaleOpenClawUpdateLaunchdJobs.mockResolvedValue([]);
213220loadGatewayTlsRuntime.mockClear();
214221inspectGatewayRestart.mockClear();
215222readGatewayRestartHandoffSync.mockClear();
@@ -440,6 +447,31 @@ describe("gatherDaemonStatus", () => {
440447expect(status.service.restartHandoff?.supervisorMode).toBe("launchd");
441448});
442449450+it.runIf(process.platform === "darwin")(
451+"surfaces stale updater launchd jobs only during deep status",
452+async () => {
453+findStaleOpenClawUpdateLaunchdJobs.mockResolvedValueOnce([
454+{
455+label: "ai.openclaw.update.2026.5.12",
456+lastExitStatus: 127,
457+},
458+]);
459+460+const status = await gatherDaemonStatus({
461+rpc: {},
462+probe: false,
463+deep: true,
464+});
465+466+expect(status.service.staleUpdateLaunchdJobs).toEqual([
467+{
468+label: "ai.openclaw.update.2026.5.12",
469+lastExitStatus: 127,
470+},
471+]);
472+},
473+);
474+443475it("does not read restart handoffs during normal status", async () => {
444476await gatherDaemonStatus({
445477rpc: {},
@@ -448,6 +480,7 @@ describe("gatherDaemonStatus", () => {
448480});
449481450482expect(readGatewayRestartHandoffSync).not.toHaveBeenCalled();
483+expect(findStaleOpenClawUpdateLaunchdJobs).not.toHaveBeenCalled();
451484});
452485453486it("uses the fast config path for plain same-file status reads", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。