import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; import { describe, expect, it, vi } from "vitest"; import { ParentAuthorizer } from "#src/authority/approval-escalator"; import { selectAuthorizer } from "#src/authority/authorizer"; import { DenyingAuthorizer } from "#src/authority/denying-authorizer"; import { LocalUserAuthorizer } from "#src/authority/local-user-authorizer"; import { makeAuthorizerSelectionDeps as makeDeps, makeDetection, } from "#test/helpers/authorizer-fixtures"; // ── Helpers ───────────────────────────────────────────────────────────────── function makeCtx(hasUI: boolean): ExtensionContext { return { hasUI, mode: "tui", ui: { select: vi.fn(), input: vi.fn(), custom: vi.fn() }, sessionManager: { getSessionId: vi.fn().mockReturnValue("session-1"), getSessionDir: vi.fn().mockReturnValue("/sessions/session-1"), getEntries: vi.fn().mockReturnValue([]), }, } as unknown as ExtensionContext; } // ── Tests ───────────────────────────────────────────────────────────────── describe("selectAuthorizer", () => { describe("terminal dispatch", () => { it("selects LocalUserAuthorizer when the context has UI", () => { const authority = selectAuthorizer(makeCtx(true), makeDeps()); expect(authority.terminal).toBeInstanceOf(LocalUserAuthorizer); }); it("selects LocalUserAuthorizer even when the context is also a subagent", () => { const authority = selectAuthorizer( makeCtx(true), makeDeps({ detection: makeDetection(true) }), ); expect(authority.terminal).toBeInstanceOf(LocalUserAuthorizer); }); it("selects ParentAuthorizer when there is no UI but the context is a subagent", () => { const authority = selectAuthorizer( makeCtx(false), makeDeps({ detection: makeDetection(true) }), ); expect(authority.terminal).toBeInstanceOf(ParentAuthorizer); }); it("selects DenyingAuthorizer when there is no UI and no subagent", () => { const authority = selectAuthorizer( makeCtx(false), makeDeps({ detection: makeDetection(false) }), ); expect(authority.terminal).toBeInstanceOf(DenyingAuthorizer); }); }); describe("chain role", () => { it("adjudicates locally when the terminal is the human", () => { const authority = selectAuthorizer(makeCtx(true), makeDeps()); expect(authority.adjudicatesLocally).toBe(true); }); it("adjudicates locally when a subagent has its own UI", () => { const authority = selectAuthorizer( makeCtx(true), makeDeps({ detection: makeDetection(true) }), ); expect(authority.adjudicatesLocally).toBe(true); }); it("relays instead of adjudicating when the terminal forwards to a serving node", () => { const authority = selectAuthorizer( makeCtx(false), makeDeps({ detection: makeDetection(true) }), ); expect(authority.adjudicatesLocally).toBe(false); }); it("adjudicates locally when the terminal denies for want of authority", () => { const authority = selectAuthorizer( makeCtx(false), makeDeps({ detection: makeDetection(false) }), ); expect(authority.adjudicatesLocally).toBe(true); }); }); });