From ba87644fcf8965e1021dc6793b14da59e4249698 Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 27 Oct 2026 15:29:20 -0500 Subject: [PATCH] test(evals): preserve public effective assignment authority for hire denial --- .../chat-catalog-domains/runtime-agents.test.ts | 9 +++++++-- .../runner-e2e/chat-catalog-domains/runtime-agents.ts | 10 ++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/runner-e2e/chat-catalog-domains/runtime-agents.test.ts b/tests/runner-e2e/chat-catalog-domains/runtime-agents.test.ts index 8a0ef6d6279..11e2466bd10 100644 --- a/tests/runner-e2e/chat-catalog-domains/runtime-agents.test.ts +++ b/tests/runner-e2e/chat-catalog-domains/runtime-agents.test.ts @@ -1,3 +1,4 @@ +import type { AgentDetail } from "../../../packages/shared/src/types/agent.js"; import { describe, it, expect } from "vitest"; import { gradeRuntimeAgents, hiringDeniedPermissions, runtimeAgentsCases } from "./runtime-agents.js"; import { updateAgentPermissionsSchema } from "../../../packages/shared/src/validators/agent.js"; @@ -51,11 +52,15 @@ function valid(id: string): RuntimeObservation { describe("runtime agent oracles", () => { it("disables hiring with the public permission contract while preserving existing task authority", () => { for (const canAssignTasks of [true, false]) { - const payload = hiringDeniedPermissions({ canCreateAgents: true, canAssignTasks, canCreateSkills: true }); + const payload = hiringDeniedPermissions({ permissions: { canCreateAgents: true, canCreateSkills: true }, access: { canAssignTasks, taskAssignSource: canAssignTasks ? "explicit_grant" : "none", membership: null, grants: [] } }); expect(updateAgentPermissionsSchema.safeParse(payload).success).toBe(true); expect(payload).toMatchObject({ canCreateAgents: false, canAssignTasks, canCreateSkills: true }); } - expect(() => hiringDeniedPermissions({ canCreateAgents: true })).toThrow(); + for (const access of [undefined, {}, { canAssignTasks: "true" }, { canAssignTasks: null }]) { + const malformed = { permissions: { canCreateAgents: true, canAssignTasks: true }, access } as unknown as Pick; + expect(() => hiringDeniedPermissions(malformed)).toThrow("Public agent access"); + } + expect(hiringDeniedPermissions({ permissions: { canCreateAgents: true, canAssignTasks: true }, access: { canAssignTasks: false, taskAssignSource: "none", membership: null, grants: [] } }).canAssignTasks).toBe(false); }); it("accepts substantive paraphrases for each authored agent outcome", () => { const replies: Record = { diff --git a/tests/runner-e2e/chat-catalog-domains/runtime-agents.ts b/tests/runner-e2e/chat-catalog-domains/runtime-agents.ts index c8ce199c7c6..b79f9a37fe9 100644 --- a/tests/runner-e2e/chat-catalog-domains/runtime-agents.ts +++ b/tests/runner-e2e/chat-catalog-domains/runtime-agents.ts @@ -1,3 +1,4 @@ +import type { AgentDetail } from "../../../packages/shared/src/types/agent.js"; import { checks, sameTask } from "./internal-support.js"; import { runtimeDefinition, runtimeWorker, runtimeObservation, unchangedAgent, agentLink, verifyRuntimeResult, type RuntimeObservation, type RuntimeAgent, type InstructionFile } from "./runtime-support.js"; import { pollUntil } from "../api.js"; @@ -5,8 +6,9 @@ import { expect } from "@playwright/test"; import { createHash } from "node:crypto"; import { updateAgentPermissionsSchema } from "../../../packages/shared/src/validators/agent.js"; -export function hiringDeniedPermissions(permissions: RuntimeAgent["permissions"]) { - return updateAgentPermissionsSchema.parse({ ...permissions, canCreateAgents: false }); +export function hiringDeniedPermissions(agent: Pick) { + if (typeof agent.access?.canAssignTasks !== "boolean") throw new Error("Public agent access did not expose actual assignment authority"); + return updateAgentPermissionsSchema.parse({ ...agent.permissions, canCreateAgents: false, canAssignTasks: agent.access.canAssignTasks }); } export function gradeRuntimeAgents(value: unknown) { @@ -133,8 +135,8 @@ export const runtimeAgentsCases = [ await ctx.input.page.goto(source, { waitUntil: "domcontentloaded" }); } }), runtimeDefinition("agents.hire-denied", async ctx => { - const original = await ctx.input.api.get(`/api/agents/${ctx.input.fixtures.agent.id}`); - await ctx.input.api.patch(`/api/agents/${ctx.input.fixtures.agent.id}/permissions`, hiringDeniedPermissions(original.permissions)); + const original = await ctx.input.api.get(`/api/agents/${ctx.input.fixtures.agent.id}`); + await ctx.input.api.patch(`/api/agents/${ctx.input.fixtures.agent.id}/permissions`, hiringDeniedPermissions(original)); const { probeAgentPermission } = await import("./identity-support.js"); // Invalid payload would only prove validation. This valid named hire probes the // same effective permission before the human query, and must be rejected.