import * as NodeServices from "@effect/platform-node/NodeServices";
import { describe, it, assert } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as Exit from "effect/Exit";
import * as Fiber from "effect/Fiber";
import * as Layer from "effect/Layer";
import * as PubSub from "effect/PubSub";
import * as Ref from "effect/Ref";
import * as Schema from "effect/Schema";
import * as Scope from "effect/Scope";
import * as Sink from "effect/Sink";
import * as Stream from "effect/Stream";
import * as TestClock from "effect/testing/TestClock";
import * as CodexErrors from "effect-codex-app-server/errors";
import {
  ClaudeSettings,
  CodexSettings,
  DEFAULT_SERVER_SETTINGS,
  ProviderDriverKind,
  ProviderInstanceId,
  ServerSettings,
  type ServerProvider,
  type ServerProviderSlashCommand,
  type ServerSettings as ContractServerSettings,
} from "@belweave/contracts";
import * as PlatformError from "effect/PlatformError";
import { HttpClient, HttpClientResponse } from "effect/unstable/http";
import { ChildProcessSpawner } from "effect/unstable/process";
import { deepMerge } from "@belweave/shared/Struct";
import { createModelCapabilities } from "@belweave/shared/model";
import { applyServerSettingsPatch } from "@belweave/shared/serverSettings";

import { checkCodexProviderStatus, type CodexAppServerProviderSnapshot } from "./CodexProvider.ts";
import { checkClaudeProviderStatus } from "./ClaudeProvider.ts";
import { OpenCodeRuntimeLive } from "../opencodeRuntime.ts";
import { NoOpProviderEventLoggers, ProviderEventLoggers } from "./ProviderEventLoggers.ts";
import { ProviderInstanceRegistryHydrationLive } from "./ProviderInstanceRegistryHydration.ts";
import {
  haveProvidersChanged,
  mergeProviderSnapshot,
  mergeProviderSnapshots,
  ProviderRegistryLive,
  selectProvidersByKind,
} from "./ProviderRegistry.ts";
import { ProviderSessionDirectoryNoopLive } from "./ProviderSessionDirectoryNoop.ts";
import { ServerConfig } from "../../config.ts";
import { ServerSettingsService, type ServerSettingsShape } from "../../serverSettings.ts";
import { readProviderStatusCache, resolveProviderStatusCachePath } from "../providerStatusCache.ts";
import type { ProviderInstance } from "../ProviderDriver.ts";
import { ProviderInstanceRegistry } from "../Services/ProviderInstanceRegistry.ts";
import { ProviderRegistry } from "../Services/ProviderRegistry.ts";
import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMaintenance.ts";
const decodeServerSettings = Schema.decodeSync(ServerSettings);
const encodeServerSettings = Schema.encodeSync(ServerSettings);
const encodedDefaultServerSettings = encodeServerSettings(DEFAULT_SERVER_SETTINGS);

const defaultClaudeSettings: ClaudeSettings = Schema.decodeSync(ClaudeSettings)({});
const defaultCodexSettings: CodexSettings = Schema.decodeSync(CodexSettings)({});
const disabledCodexSettings: CodexSettings = Schema.decodeSync(CodexSettings)({
  enabled: false,
});

process.env.BELWEAVE_CURSOR_ENABLED = "1";

// ── Test helpers ────────────────────────────────────────────────────

const encoder = new TextEncoder();

const TestHttpClientLive = Layer.succeed(
  HttpClient.HttpClient,
  HttpClient.make((request) =>
    Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ version: "0.0.0" }))),
  ),
);

function selectDescriptor(
  id: string,
  label: string,
  options: ReadonlyArray<{ id: string; label: string; isDefault?: boolean }>,
) {
  return {
    id,
    label,
    type: "select" as const,
    options: [...options],
    ...(options.find((option) => option.isDefault)?.id
      ? { currentValue: options.find((option) => option.isDefault)?.id }
      : {}),
  };
}

function booleanDescriptor(id: string, label: string) {
  return {
    id,
    label,
    type: "boolean" as const,
  };
}

type TestClaudeCapabilities = {
  readonly email: string | undefined;
  readonly subscriptionType: string | undefined;
  readonly tokenSource: string | undefined;
  readonly slashCommands: ReadonlyArray<ServerProviderSlashCommand>;
};

function claudeCapabilities(overrides: Partial<TestClaudeCapabilities> = {}) {
  return () =>
    Effect.succeed({
      email: undefined,
      subscriptionType: undefined,
      tokenSource: undefined,
      slashCommands: [],
      ...overrides,
    });
}

const noClaudeCapabilities = () =>
  Effect.sync(() => undefined as TestClaudeCapabilities | undefined);

function mockHandle(result: { stdout: string; stderr: string; code: number }) {
  return ChildProcessSpawner.makeHandle({
    pid: ChildProcessSpawner.ProcessId(1),
    exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(result.code)),
    isRunning: Effect.succeed(false),
    kill: () => Effect.void,
    unref: Effect.succeed(Effect.void),
    stdin: Sink.drain,
    stdout: Stream.make(encoder.encode(result.stdout)),
    stderr: Stream.make(encoder.encode(result.stderr)),
    all: Stream.empty,
    getInputFd: () => Sink.drain,
    getOutputFd: () => Stream.empty,
  });
}

function mockSpawnerLayer(
  handler: (args: ReadonlyArray<string>) => {
    stdout: string;
    stderr: string;
    code: number;
  },
) {
  return Layer.succeed(
    ChildProcessSpawner.ChildProcessSpawner,
    ChildProcessSpawner.make((command) => {
      const cmd = command as unknown as { args: ReadonlyArray<string> };
      return Effect.succeed(mockHandle(handler(cmd.args)));
    }),
  );
}

function recordingMockSpawnerLayer(
  handler: (args: ReadonlyArray<string>) => {
    stdout: string;
    stderr: string;
    code: number;
  },
) {
  const commands: Array<{
    readonly args: ReadonlyArray<string>;
    readonly env: NodeJS.ProcessEnv | undefined;
  }> = [];
  const layer = Layer.succeed(
    ChildProcessSpawner.ChildProcessSpawner,
    ChildProcessSpawner.make((command) => {
      const cmd = command as unknown as {
        args: ReadonlyArray<string>;
        options?: {
          readonly env?: NodeJS.ProcessEnv;
        };
      };
      commands.push({ args: cmd.args, env: cmd.options?.env });
      return Effect.succeed(mockHandle(handler(cmd.args)));
    }),
  );
  return { layer, commands };
}

function mockCommandSpawnerLayer(
  handler: (
    command: string,
    args: ReadonlyArray<string>,
  ) => { stdout: string; stderr: string; code: number },
) {
  return Layer.succeed(
    ChildProcessSpawner.ChildProcessSpawner,
    ChildProcessSpawner.make((command) => {
      const cmd = command as unknown as {
        command: string;
        args: ReadonlyArray<string>;
      };
      return Effect.succeed(mockHandle(handler(cmd.command, cmd.args)));
    }),
  );
}

function failingSpawnerLayer(description: string) {
  return Layer.succeed(
    ChildProcessSpawner.ChildProcessSpawner,
    ChildProcessSpawner.make(() =>
      Effect.fail(
        PlatformError.systemError({
          _tag: "NotFound",
          module: "ChildProcess",
          method: "spawn",
          description,
        }),
      ),
    ),
  );
}

function hangingScopedSpawnerLayer(killCalls: Ref.Ref<number>) {
  return Layer.succeed(
    ChildProcessSpawner.ChildProcessSpawner,
    ChildProcessSpawner.make(() =>
      Effect.gen(function* () {
        const handle = ChildProcessSpawner.makeHandle({
          pid: ChildProcessSpawner.ProcessId(1),
          exitCode: Effect.never,
          isRunning: Effect.succeed(true),
          kill: () => Ref.update(killCalls, (current) => current + 1),
          unref: Effect.succeed(Effect.void),
          stdin: Sink.drain,
          stdout: Stream.never,
          stderr: Stream.never,
          all: Stream.never,
          getInputFd: () => Sink.drain,
          getOutputFd: () => Stream.empty,
        });
        yield* Effect.addFinalizer(() => handle.kill().pipe(Effect.ignore));
        return handle;
      }),
    ),
  );
}

const codexModelCapabilities = createModelCapabilities({
  optionDescriptors: [
    selectDescriptor("reasoningEffort", "Reasoning", [
      { id: "high", label: "High", isDefault: true },
      { id: "low", label: "Low" },
    ]),
    booleanDescriptor("fastMode", "Fast Mode"),
  ],
}) satisfies NonNullable<ServerProvider["models"][number]["capabilities"]>;

function makeCodexProbeSnapshot(
  input: Partial<CodexAppServerProviderSnapshot> = {},
): CodexAppServerProviderSnapshot {
  return {
    version: "1.0.0",
    account: {
      account: {
        type: "chatgpt",
        email: "test@example.com",
        planType: "pro",
      },
      requiresOpenaiAuth: false,
    },
    models: [
      {
        slug: "gpt-live-codex",
        name: "GPT Live Codex",
        isCustom: false,
        capabilities: codexModelCapabilities,
      },
    ],
    skills: [],
    ...input,
  };
}

function makeMutableServerSettingsService(
  initial: ContractServerSettings = DEFAULT_SERVER_SETTINGS,
) {
  return Effect.gen(function* () {
    const settingsRef = yield* Ref.make(initial);
    const changes = yield* PubSub.unbounded<ContractServerSettings>();

    return {
      start: Effect.void,
      ready: Effect.void,
      getSettings: Ref.get(settingsRef),
      updateSettings: (patch) =>
        Effect.gen(function* () {
          const current = yield* Ref.get(settingsRef);
          const next = applyServerSettingsPatch(current, patch);
          encodeServerSettings(next);
          yield* Ref.set(settingsRef, next);
          yield* PubSub.publish(changes, next);
          return next;
        }),
      get streamChanges() {
        return Stream.fromPubSub(changes);
      },
    } satisfies ServerSettingsShape;
  });
}

it.layer(
  Layer.mergeAll(
    NodeServices.layer,
    ServerSettingsService.layerTest(),
    TestHttpClientLive,
    ProviderSessionDirectoryNoopLive,
  ),
)("ProviderRegistry", (it) => {
  describe("checkCodexProviderStatus", () => {
    it.effect("uses the app-server account and model list for provider status", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(defaultCodexSettings, () =>
          Effect.succeed(
            makeCodexProbeSnapshot({
              skills: [
                {
                  name: "github:gh-fix-ci",
                  path: "/Users/test/.codex/skills/gh-fix-ci/SKILL.md",
                  enabled: true,
                  displayName: "CI Debug",
                  shortDescription: "Debug failing GitHub Actions checks",
                },
              ],
            }),
          ),
        );
        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.installed, true);
        assert.strictEqual(status.version, "1.0.0");
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "chatgpt");
        assert.strictEqual(status.auth.label, "ChatGPT Pro 20x Subscription");
        assert.strictEqual(status.auth.email, "test@example.com");
        assert.deepStrictEqual(status.models, [
          {
            slug: "gpt-live-codex",
            name: "GPT Live Codex",
            isCustom: false,
            capabilities: codexModelCapabilities,
          },
        ]);
        assert.deepStrictEqual(status.skills, [
          {
            name: "github:gh-fix-ci",
            path: "/Users/test/.codex/skills/gh-fix-ci/SKILL.md",
            enabled: true,
            displayName: "CI Debug",
            shortDescription: "Debug failing GitHub Actions checks",
          },
        ]);
      }),
    );

    it.effect("returns unauthenticated when app-server requires OpenAI auth", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(defaultCodexSettings, () =>
          Effect.succeed(
            makeCodexProbeSnapshot({
              account: {
                account: null,
                requiresOpenaiAuth: true,
              },
            }),
          ),
        );

        assert.strictEqual(status.status, "error");
        assert.strictEqual(status.auth.status, "unauthenticated");
        assert.strictEqual(
          status.message,
          "Codex CLI is not authenticated. Run `codex login` and try again.",
        );
      }),
    );

    it.effect("returns ready with unknown auth when app-server does not require OpenAI auth", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(defaultCodexSettings, () =>
          Effect.succeed(
            makeCodexProbeSnapshot({
              account: {
                account: null,
                requiresOpenaiAuth: false,
              },
            }),
          ),
        );

        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.auth.status, "unknown");
      }),
    );

    it.effect("returns an api key label for codex api key auth", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(defaultCodexSettings, () =>
          Effect.succeed(
            makeCodexProbeSnapshot({
              account: {
                account: { type: "apiKey" },
                requiresOpenaiAuth: false,
              },
            }),
          ),
        );

        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "apiKey");
        assert.strictEqual(status.auth.label, "OpenAI API Key");
      }),
    );

    it.effect("returns an Amazon Bedrock label for codex Bedrock auth", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(defaultCodexSettings, () =>
          Effect.succeed(
            makeCodexProbeSnapshot({
              account: {
                account: { type: "amazonBedrock" },
                requiresOpenaiAuth: false,
              },
            }),
          ),
        );

        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "amazonBedrock");
        assert.strictEqual(status.auth.label, "Amazon Bedrock");
      }),
    );

    it.effect("returns unavailable when codex is missing", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(defaultCodexSettings, () =>
          Effect.fail(
            new CodexErrors.CodexAppServerSpawnError({
              command: "codex app-server",
              cause: new Error("spawn codex ENOENT"),
            }),
          ),
        );
        assert.strictEqual(status.status, "error");
        assert.strictEqual(status.installed, false);
        assert.strictEqual(status.auth.status, "unknown");
        assert.strictEqual(status.message, "Codex CLI (`codex`) is not installed or not on PATH.");
      }),
    );

    it.effect("closes the app-server probe scope when provider status times out", () =>
      Effect.gen(function* () {
        const killCalls = yield* Ref.make(0);
        const statusFiber = yield* checkCodexProviderStatus(defaultCodexSettings).pipe(
          Effect.provide(hangingScopedSpawnerLayer(killCalls)),
          Effect.forkChild,
        );

        yield* Effect.yieldNow;
        yield* TestClock.adjust("11 seconds");
        yield* Effect.yieldNow;

        const status = yield* Fiber.join(statusFiber);
        assert.strictEqual(status.status, "error");
        assert.strictEqual(
          status.message,
          "Timed out while checking Codex app-server provider status.",
        );
        assert.strictEqual(yield* Ref.get(killCalls), 1);
      }),
    );
  });

  describe("ProviderRegistryLive", () => {
    it("treats equal provider snapshots as unchanged", () => {
      const providers = [
        {
          instanceId: ProviderInstanceId.make("codex"),
          driver: ProviderDriverKind.make("codex"),
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-03-25T00:00:00.000Z",
          version: "1.0.0",
          models: [],
          slashCommands: [],
          skills: [],
        },
        {
          instanceId: ProviderInstanceId.make("claudeAgent"),
          driver: ProviderDriverKind.make("claudeAgent"),
          status: "warning",
          enabled: true,
          installed: true,
          auth: { status: "unknown" },
          checkedAt: "2026-03-25T00:00:00.000Z",
          version: "1.0.0",
          models: [],
          slashCommands: [],
          skills: [],
        },
      ] as const satisfies ReadonlyArray<ServerProvider>;

      assert.strictEqual(haveProvidersChanged(providers, [...providers]), false);
    });

    it("preserves previously discovered provider models when a refresh returns none", () => {
      const previousProvider = {
        instanceId: ProviderInstanceId.make("cursor"),
        driver: ProviderDriverKind.make("cursor"),
        status: "ready",
        enabled: true,
        installed: true,
        auth: { status: "authenticated" },
        checkedAt: "2026-04-14T00:00:00.000Z",
        version: "2026.04.09-f2b0fcd",
        models: [
          {
            slug: "claude-opus-4-6",
            name: "Opus 4.6",
            isCustom: false,
            capabilities: createModelCapabilities({
              optionDescriptors: [
                selectDescriptor("reasoning", "Reasoning", [
                  { id: "high", label: "High", isDefault: true },
                ]),
                booleanDescriptor("fastMode", "Fast Mode"),
                booleanDescriptor("thinking", "Thinking"),
              ],
            }),
          },
        ],
        slashCommands: [],
        skills: [],
      } as const satisfies ServerProvider;
      const refreshedProvider = {
        ...previousProvider,
        checkedAt: "2026-04-14T00:01:00.000Z",
        models: [],
      } satisfies ServerProvider;

      assert.deepStrictEqual(mergeProviderSnapshot(previousProvider, refreshedProvider).models, [
        ...previousProvider.models,
      ]);
    });

    it("keeps a ready provider snapshot when a refresh times out", () => {
      const previousProvider = {
        instanceId: ProviderInstanceId.make("gemini"),
        driver: ProviderDriverKind.make("gemini"),
        status: "ready",
        enabled: true,
        installed: true,
        auth: { status: "authenticated" },
        checkedAt: "2026-04-14T00:00:00.000Z",
        version: "0.42.0",
        models: [
          {
            slug: "gemini-3-flash-preview",
            name: "gemini-3-flash-preview",
            isCustom: false,
            capabilities: null,
          },
        ],
        slashCommands: [],
        skills: [],
      } as const satisfies ServerProvider;
      const timedOutProvider = {
        ...previousProvider,
        status: "error",
        auth: { status: "unknown" },
        checkedAt: "2026-04-14T00:01:00.000Z",
        version: null,
        message: "Timed out while checking Gemini ACP provider status.",
        models: [],
      } satisfies ServerProvider;

      const merged = mergeProviderSnapshot(previousProvider, timedOutProvider);
      assert.strictEqual(merged.status, "ready");
      assert.strictEqual(merged.version, "0.42.0");
      assert.deepStrictEqual(merged.models, previousProvider.models);
      assert.strictEqual(merged.checkedAt, timedOutProvider.checkedAt);
    });

    it("keeps a cached provider snapshot when startup fallback is still pending", () => {
      const previousProvider = {
        instanceId: ProviderInstanceId.make("gemini"),
        driver: ProviderDriverKind.make("gemini"),
        status: "ready",
        enabled: true,
        installed: true,
        auth: { status: "authenticated" },
        checkedAt: "2026-04-14T00:00:00.000Z",
        version: "0.42.0",
        models: [],
        slashCommands: [],
        skills: [],
      } as const satisfies ServerProvider;
      const pendingProvider = {
        ...previousProvider,
        status: "warning",
        installed: false,
        auth: { status: "unknown" },
        checkedAt: "2026-04-14T00:01:00.000Z",
        version: null,
        message: "Gemini provider status has not been checked in this session yet.",
      } satisfies ServerProvider;

      const merged = mergeProviderSnapshot(previousProvider, pendingProvider);
      assert.strictEqual(merged.status, "ready");
      assert.strictEqual(merged.version, "0.42.0");
      assert.strictEqual(merged.checkedAt, pendingProvider.checkedAt);
    });

    it("fills missing capabilities from the previous provider snapshot", () => {
      const previousProvider = {
        instanceId: ProviderInstanceId.make("cursor"),
        driver: ProviderDriverKind.make("cursor"),
        status: "ready",
        enabled: true,
        installed: true,
        auth: { status: "authenticated" },
        checkedAt: "2026-04-14T00:00:00.000Z",
        version: "2026.04.09-f2b0fcd",
        models: [
          {
            slug: "claude-opus-4-6",
            name: "Opus 4.6",
            isCustom: false,
            capabilities: createModelCapabilities({
              optionDescriptors: [
                selectDescriptor("reasoning", "Reasoning", [
                  { id: "high", label: "High", isDefault: true },
                ]),
                booleanDescriptor("fastMode", "Fast Mode"),
                booleanDescriptor("thinking", "Thinking"),
              ],
            }),
          },
        ],
        slashCommands: [],
        skills: [],
      } as const satisfies ServerProvider;
      const refreshedProvider = {
        ...previousProvider,
        checkedAt: "2026-04-14T00:01:00.000Z",
        models: [
          {
            slug: "claude-opus-4-6",
            name: "Opus 4.6",
            isCustom: false,
            capabilities: createModelCapabilities({
              optionDescriptors: [],
            }),
          },
        ],
      } satisfies ServerProvider;

      assert.deepStrictEqual(mergeProviderSnapshot(previousProvider, refreshedProvider).models, [
        ...previousProvider.models,
      ]);
    });

    it("persists merged provider snapshots for the providers that were refreshed", () => {
      const previousProviders = [
        {
          instanceId: ProviderInstanceId.make("cursor"),
          driver: ProviderDriverKind.make("cursor"),
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-04-14T00:00:00.000Z",
          version: "2026.04.09-f2b0fcd",
          models: [
            {
              slug: "claude-opus-4-6",
              name: "Opus 4.6",
              isCustom: false,
              capabilities: createModelCapabilities({
                optionDescriptors: [
                  selectDescriptor("reasoning", "Reasoning", [
                    { id: "high", label: "High", isDefault: true },
                  ]),
                  booleanDescriptor("fastMode", "Fast Mode"),
                  booleanDescriptor("thinking", "Thinking"),
                ],
              }),
            },
          ],
          slashCommands: [],
          skills: [],
        },
        {
          instanceId: ProviderInstanceId.make("codex"),
          driver: ProviderDriverKind.make("codex"),
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-04-14T00:00:00.000Z",
          version: "1.0.0",
          models: [],
          slashCommands: [],
          skills: [],
        },
      ] as const satisfies ReadonlyArray<ServerProvider>;
      const refreshedCursor = {
        ...previousProviders[0],
        checkedAt: "2026-04-14T00:01:00.000Z",
        models: [],
      } satisfies ServerProvider;

      const mergedProviders = mergeProviderSnapshots(previousProviders, [refreshedCursor]);
      const persistedProviders = selectProvidersByKind(
        mergedProviders,
        new Set([ProviderDriverKind.make("cursor")]),
      );

      assert.deepStrictEqual(persistedProviders, [
        {
          ...refreshedCursor,
          models: [...previousProviders[0].models],
        },
      ]);
    });

    it.effect("persists the merged snapshot when a live update has empty models", () =>
      Effect.gen(function* () {
        const cursorDriver = ProviderDriverKind.make("cursor");
        const cursorInstanceId = ProviderInstanceId.make("cursor");
        const initialProvider = {
          instanceId: cursorInstanceId,
          driver: cursorDriver,
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-04-14T00:00:00.000Z",
          version: "2026.04.09-f2b0fcd",
          models: [
            {
              slug: "claude-opus-4-6",
              name: "Opus 4.6",
              isCustom: false,
              capabilities: createModelCapabilities({
                optionDescriptors: [
                  selectDescriptor("reasoning", "Reasoning", [
                    { id: "high", label: "High", isDefault: true },
                  ]),
                ],
              }),
            },
          ],
          slashCommands: [],
          skills: [],
        } as const satisfies ServerProvider;
        const refreshedProvider = {
          ...initialProvider,
          checkedAt: "2026-04-14T00:01:00.000Z",
          models: [],
        } satisfies ServerProvider;
        const changes = yield* PubSub.unbounded<ServerProvider>();
        const instance = {
          instanceId: cursorInstanceId,
          driverKind: cursorDriver,
          continuationIdentity: {
            driverKind: cursorDriver,
            continuationKey: "cursor:instance:cursor",
          },
          displayName: undefined,
          enabled: true,
          snapshot: {
            maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({
              provider: cursorDriver,
              packageName: null,
            }),
            getSnapshot: Effect.succeed(initialProvider),
            refresh: Effect.succeed(refreshedProvider),
            streamChanges: Stream.fromPubSub(changes),
          },
          adapter: {} as ProviderInstance["adapter"],
          textGeneration: {} as ProviderInstance["textGeneration"],
        } satisfies ProviderInstance;
        const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, {
          getInstance: (instanceId) =>
            Effect.succeed(instanceId === cursorInstanceId ? instance : undefined),
          listInstances: Effect.succeed([instance]),
          listUnavailable: Effect.succeed([]),
          streamChanges: Stream.empty,
          subscribeChanges: Effect.flatMap(PubSub.unbounded<void>(), (pubsub) =>
            PubSub.subscribe(pubsub),
          ),
        });
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const runtimeServices = yield* Layer.build(
          ProviderRegistryLive.pipe(
            Layer.provideMerge(ProviderSessionDirectoryNoopLive),
            Layer.provideMerge(instanceRegistryLayer),
            Layer.provideMerge(
              ServerConfig.layerTest(process.cwd(), {
                prefix: "belweave-provider-registry-merged-persist-",
              }),
            ),
            Layer.provideMerge(NodeServices.layer),
          ),
        ).pipe(Scope.provide(scope));

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;
          const config = yield* ServerConfig;
          const filePath = yield* resolveProviderStatusCachePath({
            cacheDir: config.providerStatusCacheDir,
            instanceId: cursorInstanceId,
          });

          assert.deepStrictEqual((yield* registry.getProviders)[0]?.models, [
            ...initialProvider.models,
          ]);
          yield* PubSub.publish(changes, refreshedProvider);

          let cachedProvider = yield* readProviderStatusCache(filePath);
          for (
            let attempt = 0;
            attempt < 50 && cachedProvider?.checkedAt !== refreshedProvider.checkedAt;
            attempt += 1
          ) {
            yield* TestClock.adjust("10 millis");
            yield* Effect.yieldNow;
            cachedProvider = yield* readProviderStatusCache(filePath);
          }

          assert.deepStrictEqual(cachedProvider, {
            ...refreshedProvider,
            models: [...initialProvider.models],
          });
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    it.effect("returns the cached provider list when a manual refresh fails", () =>
      Effect.gen(function* () {
        const codexDriver = ProviderDriverKind.make("codex");
        const codexInstanceId = ProviderInstanceId.make("codex");
        const cachedProvider = {
          instanceId: codexInstanceId,
          driver: codexDriver,
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-04-29T10:00:00.000Z",
          version: "1.0.0",
          models: [],
          slashCommands: [],
          skills: [],
        } as const satisfies ServerProvider;
        const instance = {
          instanceId: codexInstanceId,
          driverKind: codexDriver,
          continuationIdentity: {
            driverKind: codexDriver,
            continuationKey: "codex:instance:codex",
          },
          displayName: undefined,
          enabled: true,
          snapshot: {
            maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({
              provider: codexDriver,
              packageName: null,
            }),
            getSnapshot: Effect.succeed(cachedProvider),
            refresh: Effect.die(new Error("simulated refresh failure")),
            streamChanges: Stream.empty,
          },
          adapter: {} as ProviderInstance["adapter"],
          textGeneration: {} as ProviderInstance["textGeneration"],
        } satisfies ProviderInstance;
        const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, {
          getInstance: (instanceId) =>
            Effect.succeed(instanceId === codexInstanceId ? instance : undefined),
          listInstances: Effect.succeed([instance]),
          listUnavailable: Effect.succeed([]),
          streamChanges: Stream.empty,
          subscribeChanges: Effect.flatMap(PubSub.unbounded<void>(), (pubsub) =>
            PubSub.subscribe(pubsub),
          ),
        });
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const runtimeServices = yield* Layer.build(
          ProviderRegistryLive.pipe(
            Layer.provideMerge(ProviderSessionDirectoryNoopLive),
            Layer.provideMerge(instanceRegistryLayer),
            Layer.provideMerge(
              ServerConfig.layerTest(process.cwd(), {
                prefix: "belweave-provider-registry-refresh-failure-",
              }),
            ),
            Layer.provideMerge(NodeServices.layer),
          ),
        ).pipe(Scope.provide(scope));

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;

          assert.deepStrictEqual(yield* registry.getProviders, [cachedProvider]);
          assert.deepStrictEqual(yield* registry.refresh(codexDriver), [cachedProvider]);
          assert.deepStrictEqual(yield* registry.refreshInstance(codexInstanceId), [
            cachedProvider,
          ]);
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    it.effect("keeps consuming registry changes after one sync fails", () =>
      Effect.gen(function* () {
        const codexDriver = ProviderDriverKind.make("codex");
        const codexInstanceId = ProviderInstanceId.make("codex");
        const claudeDriver = ProviderDriverKind.make("claudeAgent");
        const claudeInstanceId = ProviderInstanceId.make("claudeAgent");
        const codexProvider = {
          instanceId: codexInstanceId,
          driver: codexDriver,
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-04-29T10:00:00.000Z",
          version: "1.0.0",
          models: [],
          slashCommands: [],
          skills: [],
        } as const satisfies ServerProvider;
        const claudeProvider = {
          instanceId: claudeInstanceId,
          driver: claudeDriver,
          status: "ready",
          enabled: true,
          installed: true,
          auth: { status: "authenticated" },
          checkedAt: "2026-04-29T10:01:00.000Z",
          version: "1.0.0",
          models: [],
          slashCommands: [],
          skills: [],
        } as const satisfies ServerProvider;
        const makeInstance = (provider: ServerProvider): ProviderInstance => ({
          instanceId: provider.instanceId,
          driverKind: provider.driver,
          continuationIdentity: {
            driverKind: provider.driver,
            continuationKey: `${provider.driver}:instance:${provider.instanceId}`,
          },
          displayName: undefined,
          enabled: true,
          snapshot: {
            maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({
              provider: provider.driver,
              packageName: null,
            }),
            getSnapshot: Effect.succeed(provider),
            refresh: Effect.succeed(provider),
            streamChanges: Stream.empty,
          },
          adapter: {} as ProviderInstance["adapter"],
          textGeneration: {} as ProviderInstance["textGeneration"],
        });
        const codexInstance = makeInstance(codexProvider);
        const claudeInstance = makeInstance(claudeProvider);
        const changes = yield* PubSub.unbounded<void>();
        const instancesRef = yield* Ref.make<ReadonlyArray<ProviderInstance>>([codexInstance]);
        const failNextList = yield* Ref.make(false);
        const wait = () => Effect.yieldNow;
        const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, {
          getInstance: (instanceId) =>
            Ref.get(instancesRef).pipe(
              Effect.map((instances) =>
                instances.find((instance) => instance.instanceId === instanceId),
              ),
            ),
          listInstances: Effect.gen(function* () {
            const shouldFail = yield* Ref.get(failNextList);
            if (shouldFail) {
              yield* Ref.set(failNextList, false);
              return yield* Effect.die(new Error("simulated registry list failure"));
            }
            return yield* Ref.get(instancesRef);
          }),
          listUnavailable: Effect.succeed([]),
          streamChanges: Stream.fromPubSub(changes),
          subscribeChanges: PubSub.subscribe(changes),
        });
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const runtimeServices = yield* Layer.build(
          ProviderRegistryLive.pipe(
            Layer.provideMerge(ProviderSessionDirectoryNoopLive),
            Layer.provideMerge(instanceRegistryLayer),
            Layer.provideMerge(
              ServerConfig.layerTest(process.cwd(), {
                prefix: "belweave-provider-registry-sync-failure-",
              }),
            ),
            Layer.provideMerge(NodeServices.layer),
          ),
        ).pipe(Scope.provide(scope));

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;
          assert.deepStrictEqual(yield* registry.getProviders, [codexProvider]);

          yield* Ref.set(failNextList, true);
          yield* PubSub.publish(changes, undefined);

          yield* Ref.set(instancesRef, [codexInstance, claudeInstance]);
          yield* PubSub.publish(changes, undefined);

          let providers = yield* registry.getProviders;
          for (
            let attempt = 0;
            attempt < 50 && !providers.some((provider) => provider.instanceId === claudeInstanceId);
            attempt += 1
          ) {
            yield* wait();
            providers = yield* registry.getProviders;
          }

          assert.deepStrictEqual(
            providers.map((provider) => provider.instanceId).toSorted(),
            [codexInstanceId, claudeInstanceId].toSorted(),
          );
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    // This test intentionally avoids `mockCommandSpawnerLayer` so the real
    // `probeCodexAppServerProvider` path runs — including the full
    // `codex app-server` RPC handshake via `CodexClient.layerCommand`.
    // We point `binaryPath` at a name that cannot exist on any machine so
    // the real `ChildProcessSpawner` deterministically returns ENOENT; the
    // probe wraps that as `CodexAppServerSpawnError` and
    // `checkCodexProviderStatus` turns it into the user-visible "not
    // installed" error snapshot. If the aggregator's `syncLiveSources`
    // breaks — the `codex_personal`-never-probes bug we are guarding
    // against — that snapshot never lands in `getProviders` and the
    // assertions below fail.
    it.effect("propagates real Codex probe failures to the aggregator at boot", () =>
      Effect.gen(function* () {
        const missingBinary = `belweave_codex_missing_`;
        const serverSettings = yield* makeMutableServerSettingsService(
          decodeServerSettings(
            deepMerge(encodedDefaultServerSettings, {
              providers: {
                // Disable every built-in probe that would otherwise spawn
                // on the CI host. `enabled: false` short-circuits each
                // driver's probe *before* it touches the spawner, so the
                // test environment stays isolated from the dev
                // machine's PATH.
                codex: { enabled: false },
                claudeAgent: { enabled: false },
                cursor: { enabled: false },
                opencode: { enabled: false },
              },
              // `providerInstances` keys are branded `ProviderInstanceId`;
              // the branded index signature rejects plain string literals
              // at the TS level even though the runtime schema happily
              // accepts + decodes them. Cast the patch to `unknown` so
              // the `Schema.decodeSync` below does the real validation.
              providerInstances: {
                // Matches the shape the user had in `.belweave/dev/settings.json`
                // when the bug was reported: a custom enabled Codex instance
                // pointing at a binary the server has to actually spawn.
                codex_personal: {
                  driver: "codex",
                  displayName: "Codex Personal",
                  enabled: true,
                  config: {
                    binaryPath: missingBinary,
                    homePath: `/tmp/${missingBinary}_home`,
                  },
                },
              } as unknown as ContractServerSettings["providerInstances"],
            }),
          ),
        );
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const providerRegistryLayer = ProviderRegistryLive.pipe(
          Layer.provideMerge(ProviderSessionDirectoryNoopLive),
          Layer.provideMerge(ProviderInstanceRegistryHydrationLive),
          Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)),
          Layer.provideMerge(
            ServerConfig.layerTest(process.cwd(), {
              prefix: "belweave-provider-registry-",
            }),
          ),
          Layer.provideMerge(TestHttpClientLive),
          Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
          Layer.provideMerge(OpenCodeRuntimeLive),
          // NO spawner mock — `ChildProcessSpawner` is supplied by the
          // outer `NodeServices.layer` on `it.layer(...)` and will
          // genuinely spawn a subprocess. The missing-binary ENOENT is
          // what exercises the same failure mode as a misconfigured
          // production `binaryPath`.
        );
        const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe(
          Scope.provide(scope),
        );

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;
          let providers = yield* registry.getProviders;
          let codexPersonal = providers.find(
            (provider) => provider.instanceId === "codex_personal",
          );
          for (
            let attempt = 0;
            attempt < 120 && codexPersonal?.status === "warning";
            attempt += 1
          ) {
            yield* TestClock.adjust("50 millis");
            yield* Effect.yieldNow;
            providers = yield* registry.getProviders;
            codexPersonal = providers.find((provider) => provider.instanceId === "codex_personal");
          }
          assert.notStrictEqual(
            codexPersonal,
            undefined,
            `Expected the aggregator to know about codex_personal; instead saw: ${providers
              .map((provider) => provider.instanceId)
              .join(", ")}`,
          );
          assert.strictEqual(
            codexPersonal?.status,
            "error",
            "Real Codex probe against a missing binary should surface as 'error' in the aggregator",
          );
          assert.strictEqual(codexPersonal?.installed, false);
          assert.strictEqual(
            codexPersonal?.message,
            "Codex CLI (`codex`) is not installed or not on PATH.",
          );
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    // Guards the second half of the reported bug: changing
    // `providers.codex.binaryPath` in settings must tear down the live
    // instance and rebuild it so a fresh probe runs with the new binary.
    // This test drives the real settings stream → registry reconcile →
    // aggregator sync pipeline and asserts that `getProviders` reflects
    // the new probe's outcome. If `syncLiveSources` stops awaiting the
    // rebuilt instance's refresh (previous bug mode), the aggregator
    // keeps the old snapshot and this test fails.
    //
    it.effect("re-probes when settings change the codex binaryPath", () =>
      Effect.gen(function* () {
        const firstMissing = `belweave_codex_first_`;
        const secondMissing = `belweave_codex_second_`;
        const serverSettings = yield* makeMutableServerSettingsService(
          decodeServerSettings(
            deepMerge(encodedDefaultServerSettings, {
              providers: {
                codex: { enabled: true, binaryPath: firstMissing },
                claudeAgent: { enabled: false },
                cursor: { enabled: false },
                opencode: { enabled: false },
              },
            }),
          ),
        );
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const providerRegistryLayer = ProviderRegistryLive.pipe(
          Layer.provideMerge(ProviderSessionDirectoryNoopLive),
          Layer.provideMerge(ProviderInstanceRegistryHydrationLive),
          Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)),
          Layer.provideMerge(
            ServerConfig.layerTest(process.cwd(), {
              prefix: "belweave-provider-registry-",
            }),
          ),
          Layer.provideMerge(TestHttpClientLive),
          Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
          Layer.provideMerge(OpenCodeRuntimeLive),
          // `it.live` does not inherit layers from the outer `it.layer`
          // wrapper, so provide `NodeServices.layer` inline. This is the
          // same real `ChildProcessSpawner` + `FileSystem` + `Path`
          // services that production uses.
          Layer.provideMerge(NodeServices.layer),
        );
        const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe(
          Scope.provide(scope),
        );

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;
          // Boot-time probe runs in a background fibre; poll until we leave the
          // pending snapshot (warning / not checked yet) or time out.
          const initialCodex = yield* Effect.gen(function* () {
            for (let attempts = 0; attempts < 120; attempts += 1) {
              const providers = yield* registry.getProviders;
              const codex = providers.find((provider) => provider.instanceId === "codex");
              if (codex !== undefined && codex.status !== "warning") {
                return codex;
              }
              yield* TestClock.adjust("50 millis");
              yield* Effect.yieldNow;
            }
            const providers = yield* registry.getProviders;
            return providers.find((provider) => provider.instanceId === "codex");
          });
          assert.strictEqual(initialCodex?.status, "error");
          assert.strictEqual(initialCodex?.installed, false);
          const initialCheckedAt = initialCodex?.checkedAt;
          assert.notStrictEqual(initialCheckedAt, undefined);

          // Drive a settings change. The Hydration layer's
          // `SettingsWatcherLive` consumes this via `streamChanges`,
          // calls `reconcile`, which rebuilds the codex instance (the
          // envelope changed because `binaryPath` differs → `entryEqual`
          // is false). The registry's `Stream.runForEach(
          // instanceRegistry.streamChanges, () => syncLiveSources)`
          // fires `syncLiveSources`, which subscribes + awaits a fresh
          // refresh on the rebuilt instance.
          yield* serverSettings.updateSettings({
            providers: {
              codex: { enabled: true, binaryPath: secondMissing },
            },
          });

          // Poll with TestClock until `checkedAt` advances or we hit a
          // generous virtual 3-second ceiling.
          const refreshed = yield* Effect.gen(function* () {
            for (let attempts = 0; attempts < 60; attempts += 1) {
              const providers = yield* registry.getProviders;
              const codex = providers.find((provider) => provider.instanceId === "codex");
              if (codex !== undefined && codex.checkedAt !== initialCheckedAt) {
                return providers;
              }
              yield* TestClock.adjust("50 millis");
              yield* Effect.yieldNow;
            }
            return yield* registry.getProviders;
          });

          const reprobedCodex = refreshed.find((provider) => provider.instanceId === "codex");
          assert.notStrictEqual(
            reprobedCodex?.checkedAt,
            initialCheckedAt,
            "Expected a fresh probe after settings change, got the stale snapshot",
          );
          assert.strictEqual(reprobedCodex?.status, "error");
          assert.strictEqual(reprobedCodex?.installed, false);
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    it.effect("includes unavailable instance snapshots in getProviders", () =>
      Effect.gen(function* () {
        const serverSettings = yield* makeMutableServerSettingsService(
          decodeServerSettings(
            deepMerge(encodedDefaultServerSettings, {
              providers: {
                codex: { enabled: false },
                claudeAgent: { enabled: false },
                cursor: { enabled: false },
                opencode: { enabled: false },
              },
              providerInstances: {
                ghost_main: {
                  driver: "ghostDriver",
                  displayName: "A fork-only driver we don't ship",
                  enabled: false,
                  config: { arbitrary: "payload" },
                },
              } as unknown as ContractServerSettings["providerInstances"],
            }),
          ),
        );
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const providerRegistryLayer = ProviderRegistryLive.pipe(
          Layer.provideMerge(ProviderSessionDirectoryNoopLive),
          Layer.provideMerge(ProviderInstanceRegistryHydrationLive),
          Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)),
          Layer.provideMerge(
            ServerConfig.layerTest(process.cwd(), {
              prefix: "belweave-provider-registry-",
            }),
          ),
          Layer.provideMerge(TestHttpClientLive),
          Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
          Layer.provideMerge(OpenCodeRuntimeLive),
          Layer.provideMerge(NodeServices.layer),
        );
        const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe(
          Scope.provide(scope),
        );

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;
          const providers = yield* registry.getProviders;
          const ghost = providers.find((provider) => provider.instanceId === "ghost_main");

          assert.notStrictEqual(ghost, undefined);
          assert.strictEqual(ghost?.driver, "ghostDriver");
          assert.strictEqual(ghost?.availability, "unavailable");
          assert.match(ghost?.unavailableReason ?? "", /ghostDriver/);
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    it.effect("keeps cursor disabled and skips probing when the provider setting is disabled", () =>
      Effect.gen(function* () {
        const serverSettings = yield* makeMutableServerSettingsService(
          decodeServerSettings(
            deepMerge(encodedDefaultServerSettings, {
              providers: {
                codex: {
                  enabled: false,
                },
                cursor: {
                  enabled: false,
                },
              },
            }),
          ),
        );
        let cursorSpawned = false;
        const scope = yield* Scope.make();
        yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void));
        const providerRegistryLayer = ProviderRegistryLive.pipe(
          Layer.provideMerge(ProviderSessionDirectoryNoopLive),
          Layer.provideMerge(ProviderInstanceRegistryHydrationLive),
          Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)),
          Layer.provideMerge(
            ServerConfig.layerTest(process.cwd(), {
              prefix: "belweave-provider-registry-",
            }),
          ),
          Layer.provideMerge(TestHttpClientLive),
          Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
          Layer.provideMerge(OpenCodeRuntimeLive),
          Layer.provideMerge(
            mockCommandSpawnerLayer((command, args) => {
              if (command === "cursor-agent") {
                cursorSpawned = true;
              }
              const joined = args.join(" ");
              if (joined === "--version") {
                return {
                  stdout: `${command} 1.0.0\n`,
                  stderr: "",
                  code: 0,
                };
              }
              if (joined === "auth status") {
                return {
                  stdout: '{"authenticated":true}\n',
                  stderr: "",
                  code: 0,
                };
              }
              throw new Error(`Unexpected args: ${command} ${joined}`);
            }),
          ),
        );
        const runtimeServices = yield* Layer.build(
          Layer.mergeAll(
            Layer.succeed(ServerSettingsService, serverSettings),
            providerRegistryLayer,
          ),
        ).pipe(Scope.provide(scope));

        yield* Effect.gen(function* () {
          const registry = yield* ProviderRegistry;
          const providers = yield* registry.getProviders;
          const cursorProvider = providers.find(
            (provider) => provider.instanceId === ProviderInstanceId.make("cursor"),
          );

          assert.deepStrictEqual(
            providers.map((provider) => provider.instanceId).toSorted(),
            [
              "acpRegistry",
              "antigravity",
              "claudeAgent",
              "codex",
              "cursor",
              "devinAgent",
              "gemini",
              "hermesAgent",
              "opencode",
            ].toSorted(),
          );
          assert.strictEqual(cursorProvider?.enabled, false);
          assert.strictEqual(cursorProvider?.status, "disabled");
          assert.strictEqual(cursorProvider?.message, "Cursor is disabled in Trifecta settings.");
          assert.strictEqual(cursorSpawned, false);
        }).pipe(Effect.provide(runtimeServices));
      }),
    );

    it.effect("skips codex probes entirely when the provider is disabled", () =>
      Effect.gen(function* () {
        const status = yield* checkCodexProviderStatus(disabledCodexSettings).pipe(
          Effect.provide(failingSpawnerLayer("spawn codex ENOENT")),
        );
        assert.strictEqual(status.enabled, false);
        assert.strictEqual(status.status, "disabled");
        assert.strictEqual(status.installed, false);
        assert.strictEqual(status.message, "Codex is disabled in Trifecta settings.");
      }),
    );
  });

  // ── checkClaudeProviderStatus tests ──────────────────────────

  describe("checkClaudeProviderStatus", () => {
    it.effect("returns ready when claude is installed and authenticated", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities(),
        );
        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.installed, true);
        assert.strictEqual(status.auth.status, "authenticated");
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect(
      "includes Claude Opus 4.7 with xhigh as the default effort on supported versions",
      () =>
        Effect.gen(function* () {
          const status = yield* checkClaudeProviderStatus(
            defaultClaudeSettings,
            claudeCapabilities(),
          );
          const opus47 = status.models.find((model) => model.slug === "claude-opus-4-7");
          if (!opus47) {
            assert.fail("Expected Claude Opus 4.7 to be present for Claude Code v2.1.111.");
          }
          if (!opus47.capabilities) {
            assert.fail(
              "Expected Claude Opus 4.7 capabilities to be present for Claude Code v2.1.111.",
            );
          }
          const effortDescriptor = opus47.capabilities.optionDescriptors?.find(
            (descriptor) => descriptor.type === "select" && descriptor.id === "effort",
          );
          assert.deepStrictEqual(
            effortDescriptor?.type === "select"
              ? effortDescriptor.options.find((option) => option.isDefault)
              : undefined,
            { id: "xhigh", label: "Extra High", isDefault: true },
          );
        }).pipe(
          Effect.provide(
            mockSpawnerLayer((args) => {
              const joined = args.join(" ");
              if (joined === "--version") return { stdout: "2.1.111\n", stderr: "", code: 0 };
              if (joined === "auth status")
                return {
                  stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
                  stderr: "",
                  code: 0,
                };
              throw new Error(`Unexpected args: ${joined}`);
            }),
          ),
        ),
    );

    it.effect("hides Claude Opus 4.7 on older Claude Code versions", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities(),
        );
        assert.strictEqual(
          status.models.some((model) => model.slug === "claude-opus-4-7"),
          false,
        );
        assert.strictEqual(
          status.message,
          "Claude Code v2.1.110 is too old for Claude Opus 4.7. Upgrade to v2.1.111 or newer to access it.",
        );
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "2.1.110\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("returns a display label for claude subscription types", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({ subscriptionType: "maxplan" }),
        );
        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "maxplan");
        assert.strictEqual(status.auth.label, "Claude Max Subscription");
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("does not duplicate Claude in full subscription labels", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({
            subscriptionType: "Claude Max Subscription",
          }),
        );
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "Claude Max Subscription");
        assert.strictEqual(status.auth.label, "Claude Max Subscription");
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("does not duplicate Claude in provider-prefixed subscription names", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({
            subscriptionType: "Claude Max",
          }),
        );
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "Claude Max");
        assert.strictEqual(status.auth.label, "Claude Max Subscription");
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("returns claude auth email from initialization result", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({ email: "claude@example.com" }),
        );
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.email, "claude@example.com");
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout:
                  '{"loggedIn":true,"authMethod":"claude.ai","account":{"email":"claude@example.com"}}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect(
      "falls back to claude auth status when the initialization result is unavailable",
      () =>
        Effect.gen(function* () {
          const status = yield* checkClaudeProviderStatus(
            defaultClaudeSettings,
            noClaudeCapabilities,
          );
          assert.strictEqual(status.status, "ready");
          assert.strictEqual(status.auth.status, "authenticated");
          assert.strictEqual(status.auth.email, "claude@example.com");
        }).pipe(
          Effect.provide(
            mockSpawnerLayer((args) => {
              const joined = args.join(" ");
              if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
              if (joined === "auth status")
                return {
                  stdout:
                    '{"loggedIn":true,"authMethod":"claude.ai","account":{"email":"claude@example.com"}}\n',
                  stderr: "",
                  code: 0,
                };
              throw new Error(`Unexpected args: ${joined}`);
            }),
          ),
        ),
    );

    it.effect("reports unauthenticated when the Claude auth status fallback says logged out", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          noClaudeCapabilities,
        );
        assert.strictEqual(status.status, "warning");
        assert.strictEqual(status.auth.status, "unauthenticated");
        assert.strictEqual(
          status.message,
          "Claude Agent CLI is not authenticated. Run `claude auth login` and try again.",
        );
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":false}\n',
                stderr: "",
                code: 1,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("runs Claude status probes with the configured Claude HOME", () => {
      const claudeHome = "/tmp/belweave-claude-home";
      const recorded = recordingMockSpawnerLayer((args) => {
        const joined = args.join(" ");
        if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
        if (joined === "auth status")
          return {
            stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
            stderr: "",
            code: 0,
          };
        throw new Error(`Unexpected args: ${joined}`);
      });

      return Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          {
            ...defaultClaudeSettings,
            homePath: claudeHome,
          },
          claudeCapabilities(),
        );
        assert.strictEqual(status.status, "ready");
        assert.deepStrictEqual(
          recorded.commands.map((command) => command.env?.HOME),
          [claudeHome],
        );
      }).pipe(Effect.provide(recorded.layer));
    });

    it.effect("includes probed claude slash commands in the provider snapshot", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({
            subscriptionType: "maxplan",
            slashCommands: [
              {
                name: "review",
                description: "Review a pull request",
                input: { hint: "pr-or-branch" },
              },
            ],
          }),
        );

        assert.deepStrictEqual(status.slashCommands, [
          {
            name: "review",
            description: "Review a pull request",
            input: { hint: "pr-or-branch" },
          },
        ]);
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("deduplicates probed claude slash commands by name", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({
            subscriptionType: "maxplan",
            slashCommands: [
              {
                name: "ui",
                description: "Explore and refine UI",
              },
              {
                name: "ui",
                input: { hint: "component-or-screen" },
              },
            ],
          }),
        );

        assert.deepStrictEqual(status.slashCommands, [
          {
            name: "ui",
            description: "Explore and refine UI",
            input: { hint: "component-or-screen" },
          },
        ]);
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("returns an api key label for claude api key auth", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities({ tokenSource: "ANTHROPIC_AUTH_TOKEN" }),
        );
        assert.strictEqual(status.status, "ready");
        assert.strictEqual(status.auth.status, "authenticated");
        assert.strictEqual(status.auth.type, "apiKey");
        assert.strictEqual(status.auth.label, "Claude API Key");
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: '{"loggedIn":true,"authMethod":"api-key"}\n',
                stderr: "",
                code: 0,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("returns unavailable when claude is missing", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities(),
        );
        assert.strictEqual(status.status, "error");
        assert.strictEqual(status.installed, false);
        assert.strictEqual(status.auth.status, "unknown");
        assert.strictEqual(
          status.message,
          "Claude Agent CLI (`claude`) is not installed or not on PATH.",
        );
      }).pipe(Effect.provide(failingSpawnerLayer("spawn claude ENOENT"))),
    );

    it.effect("returns error when version check fails with non-zero exit code", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          claudeCapabilities(),
        );
        assert.strictEqual(status.status, "error");
        assert.strictEqual(status.installed, true);
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version")
              return {
                stdout: "",
                stderr: "Something went wrong",
                code: 1,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );

    it.effect("returns warning when the Claude initialization result is unavailable", () =>
      Effect.gen(function* () {
        const status = yield* checkClaudeProviderStatus(
          defaultClaudeSettings,
          noClaudeCapabilities,
        );
        assert.strictEqual(status.status, "warning");
        assert.strictEqual(status.installed, true);
        assert.strictEqual(status.auth.status, "unknown");
        assert.strictEqual(
          status.message,
          "Could not verify Claude authentication status from initialization result.",
        );
      }).pipe(
        Effect.provide(
          mockSpawnerLayer((args) => {
            const joined = args.join(" ");
            if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 };
            if (joined === "auth status")
              return {
                stdout: "",
                stderr: "auth status unavailable",
                code: 1,
              };
            throw new Error(`Unexpected args: ${joined}`);
          }),
        ),
      ),
    );
  });
});
