



















@@ -312,7 +312,7 @@ describe("maybeRepairGatewayDaemon", () => {
312312healthOk: false,
313313});
314314315-expect(readGatewayRestartHandoffSync).toHaveBeenCalledOnce();
315+expect(readGatewayRestartHandoffSync).toHaveBeenCalledTimes(2);
316316const [handoffEnv] = readGatewayRestartHandoffSync.mock.calls[0] as unknown as [
317317{ OPENCLAW_STATE_DIR?: string; OPENCLAW_CONFIG_PATH?: string },
318318];
@@ -324,12 +324,12 @@ describe("maybeRepairGatewayDaemon", () => {
324324);
325325});
326326327-it("does not read restart handoffs during normal doctor", async () => {
327+it("does not inspect port connections during normal doctor", async () => {
328328setPlatform("linux");
329329330330await runNonInteractiveRepair();
331331332-expect(readGatewayRestartHandoffSync).not.toHaveBeenCalled();
332+expect(readGatewayRestartHandoffSync).toHaveBeenCalled();
333333expect(inspectPortConnections).not.toHaveBeenCalled();
334334});
335335@@ -551,4 +551,74 @@ describe("maybeRepairGatewayDaemon", () => {
551551expect(service.install).not.toHaveBeenCalled();
552552expect(note).toHaveBeenCalledWith(EXTERNAL_SERVICE_REPAIR_NOTE, "Gateway LaunchAgent");
553553});
554+555+it("skips restart prompt when gateway is healthy after recent restart handoff in normal doctor flow", async () => {
556+vi.useFakeTimers();
557+vi.setSystemTime(40_000);
558+setPlatform("linux");
559+const handoff = {
560+kind: "gateway-supervisor-restart-handoff" as const,
561+version: 1 as const,
562+intentId: "intent-healthy",
563+pid: 99_999,
564+createdAt: 35_000,
565+expiresAt: 95_000,
566+reason: "update.run",
567+source: "gateway-update" as const,
568+restartKind: "update-process" as const,
569+supervisorMode: "systemd" as const,
570+} satisfies GatewayRestartHandoff;
571+readGatewayRestartHandoffSync.mockReturnValue(handoff);
572+573+await maybeRepairGatewayDaemon({
574+cfg: { gateway: {} },
575+runtime: { log: vi.fn(), error: vi.fn(), exit: vi.fn() },
576+prompter: createPrompter(() => true),
577+options: { deep: false },
578+gatewayDetailsMessage: "details",
579+healthOk: false,
580+});
581+582+expect(readGatewayRestartHandoffSync).toHaveBeenCalled();
583+expect(healthCommand).toHaveBeenCalledOnce();
584+expect(service.restart).not.toHaveBeenCalled();
585+expect(note).toHaveBeenCalledWith(
586+"Gateway is healthy after recent restart; skipping restart prompt.",
587+"Gateway",
588+);
589+});
590+591+it("prompts for restart when health probe fails despite recent restart handoff in normal doctor flow", async () => {
592+vi.useFakeTimers();
593+vi.setSystemTime(40_000);
594+setPlatform("linux");
595+const handoff = {
596+kind: "gateway-supervisor-restart-handoff" as const,
597+version: 1 as const,
598+intentId: "intent-unhealthy",
599+pid: 88_888,
600+createdAt: 35_000,
601+expiresAt: 95_000,
602+reason: "gateway.restart",
603+source: "operator-restart" as const,
604+restartKind: "full-process" as const,
605+supervisorMode: "systemd" as const,
606+} satisfies GatewayRestartHandoff;
607+readGatewayRestartHandoffSync.mockReturnValue(handoff);
608+healthCommand.mockRejectedValueOnce(new Error("gateway closed"));
609+610+await maybeRepairGatewayDaemon({
611+cfg: { gateway: {} },
612+runtime: { log: vi.fn(), error: vi.fn(), exit: vi.fn() },
613+prompter: createPrompter(() => false),
614+options: { deep: false },
615+gatewayDetailsMessage: "details",
616+healthOk: false,
617+});
618+619+expect(readGatewayRestartHandoffSync).toHaveBeenCalled();
620+expect(healthCommand).toHaveBeenCalledOnce();
621+expect(service.restart).not.toHaveBeenCalled();
622+// The restart prompt was shown but user declined (createPrompter returned false for it).
623+});
554624});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。