diff --git a/ui/src/adapters/codex-local/config-fields.test.tsx b/ui/src/adapters/codex-local/config-fields.test.tsx index 47ca43073d..205634f74c 100644 --- a/ui/src/adapters/codex-local/config-fields.test.tsx +++ b/ui/src/adapters/codex-local/config-fields.test.tsx @@ -30,7 +30,7 @@ describe("Paperclip Runner Codex configuration", () => { expect(html).toContain(''); expect(html).toContain("OpenCode 1.18.32"); - expect(html).toContain("ACPX"); + expect(html).toContain(''); expect(html).not.toContain("Permission mode"); expect(html).not.toContain("Ask when requested"); expect(html).not.toContain("Ask for untrusted operations"); @@ -54,15 +54,19 @@ describe("Paperclip Runner Codex configuration", () => { expect(html).not.toContain("Ask for untrusted operations"); }); - it("offers ACPX Claude without a redundant agent selector", () => { + it("offers qualified Claude and keeps candidate ACP agents visibly disabled", () => { const html = renderRunner({ provider: "acpx", acpxAgent: "claude", acpxPermissionMode: "approve-reads", }); - expect(html).toContain(''); - expect(html).not.toContain("ACP agent"); + expect(html).toContain(''); + expect(html).toContain("ACP agent"); + expect(html).toContain(''); + expect(html).toContain(''); + expect(html).toContain(''); + expect(html).toContain(''); expect(html).not.toContain("Codex via ACPX"); expect(html).not.toContain("ACPX Codex"); expect(html).not.toContain("Pi via ACPX"); diff --git a/ui/src/adapters/config-sections.test.tsx b/ui/src/adapters/config-sections.test.tsx index 42a27e2235..5903e75e40 100644 --- a/ui/src/adapters/config-sections.test.tsx +++ b/ui/src/adapters/config-sections.test.tsx @@ -60,13 +60,26 @@ describe("adapter configuration sections", () => { "runPolicy", config, ); - expect(adapter).toContain("ACPX Claude"); + expect(adapter).toContain(''); expect(adapter).not.toContain("Runner lifecycle"); expect(configuration).not.toContain("Permission mode"); expect(configuration).not.toContain("Runner lifecycle"); expect(policy).toContain("Runner lifecycle"); expect(policy).toContain('value="45000"'); - expect(policy).not.toContain("ACPX Claude"); + expect(policy).not.toContain("ACP agents"); + }); + + it("keeps ACP agent admission choices in the adapter section", () => { + const config = { provider: "acpx", acpxAgent: "claude" }; + const adapter = renderSection(CodexLocalConfigFields, "paperclip_runner", "adapter", config); + const policy = renderSection(CodexLocalConfigFields, "paperclip_runner", "runPolicy", config); + + expect(adapter).toContain(''); + expect(adapter).toContain(''); + expect(adapter).not.toContain("Runner lifecycle"); + expect(policy).toContain("Runner lifecycle"); + expect(policy).not.toContain("ACP agent"); + expect(policy).not.toContain("qualification pending"); }); it.each([ diff --git a/ui/src/components/task-chat/TaskChatProtocolActivityRow.test.tsx b/ui/src/components/task-chat/TaskChatProtocolActivityRow.test.tsx index bb2fb87944..f9e956e2c4 100644 --- a/ui/src/components/task-chat/TaskChatProtocolActivityRow.test.tsx +++ b/ui/src/components/task-chat/TaskChatProtocolActivityRow.test.tsx @@ -178,7 +178,7 @@ describe("TaskChatProtocolActivityRow", () => { expect(row?.querySelector('[data-testid="task-chat-protocol-activity-icon"]')?.querySelectorAll("path")).toHaveLength(3); }); - it("shows a notice as a warning and full-width message without metadata or a disclosure", () => { + it("keeps a notice readable and preserves metadata in a collapsed disclosure", () => { const summary = "Project-local configuration is disabled.\nTrust the repository to load its hooks."; render({ id: "notice", kind: "protocol", surface: "provider_activity", family: "provider_notice", @@ -186,12 +186,26 @@ describe("TaskChatProtocolActivityRow", () => { details: [ { label: "Category", value: "configWarning" }, { label: "Recoverable", value: "Yes" }, + { label: "Provider", value: "pi" }, + { label: "Provenance", value: "provider_native" }, { label: "Summary", value: summary }, ], steps: [], links: [], children: [], }); - expect(container.textContent).toBe(`Warning${summary}`); + expect(container.textContent).toContain(`Warning${summary}`); expect(container.querySelector("p")?.textContent).toBe(summary); - expect(container.querySelector("dl")).toBeNull(); + const disclosure = container.querySelector("details"); + expect(disclosure).not.toBeNull(); + expect(disclosure?.open).toBe(false); + expect(disclosure?.querySelector("summary")?.textContent).toBe("Details"); + expect(Array.from(disclosure?.querySelectorAll("dt") ?? [], (term) => term.textContent)).toEqual([ + "Category", "Recoverable", "Provider", "Provenance", + ]); + expect(Array.from(disclosure?.querySelectorAll("dd") ?? [], (value) => value.textContent)).toEqual([ + "configWarning", "Yes", "pi", "provider_native", + ]); + expect(disclosure?.textContent).not.toContain(summary); + act(() => disclosure?.querySelector("summary")?.click()); + expect(disclosure?.open).toBe(true); expect(container.querySelector("button")).toBeNull(); expect(container.querySelector('[data-testid="task-chat-protocol-activity-icon"]')).not.toBeNull(); }); @@ -214,6 +228,7 @@ describe("TaskChatProtocolActivityRow", () => { const row = container.querySelector('[data-testid="task-chat-protocol-activity-row"]'); expect(row?.querySelector("button")).toBeNull(); + expect(row?.querySelector("details")).toBeNull(); expect(row?.querySelector('[aria-expanded]')).toBeNull(); }); });