Files
PaperClipAI/tests/runner-e2e/chat-catalog-domains/runtime-hiring.test.ts
T

35 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { it, expect } from "vitest";
import { gradeGovernedHire } from "./runtime-hiring.js";
function valid() {
const proposal = (id: string, name: string) => ({ id, companyId: "company", type: "hire_agent", status: "pending", requestedByAgentId: "ceo", decidedByUserId: null as string | null,
payload: { agentId: name.toLowerCase(), name, role: "qa", adapterType: "runner", adapterConfig: { model: "admitted" } } });
const firstProposal = proposal("first", "Morgan"), secondProposal = proposal("second", "Jules");
const acceptedBefore = { id: "jules", companyId: "company", name: "Jules", role: "qa", adapterType: "runner", adapterConfig: { model: "admitted" } };
return { scenarioId: "agents.hire-needs-approval", origin: "http://fixture.invalid", companyId: "company", leadId: "ceo",
state: { firstProposal, secondProposal, approvalsAfter: [{ ...firstProposal, status: "rejected", decidedByUserId: "human" }, { ...secondProposal, status: "approved", decidedByUserId: "human" }],
secondRequestAttributed: true, rejectedBeforeChangedRequest: true, noRepeatedProposalBeforeChangedRequest: true, acceptedBefore,
noWorkerBeforeFirstDecision: true, noWorkerBeforeSecondDecision: true, requestRunIds: ["canonical", "changed"],
firstReply: "Morgan's QA proposal is pending board approval.", secondReply: "Jules's QA proposal is awaiting approval." },
agents: [{ ...acceptedBefore, status: "idle", lifecycleState: "ready" }], tasks: [], links: [], activity: [], humanQueries: [], reply: "",
runs: [{ id: "canonical", agentId: "ceo", status: "succeeded", contextSnapshot: {} as Record<string, unknown> }, { id: "changed", agentId: "ceo", status: "succeeded", contextSnapshot: {} as Record<string, unknown> }] };
}
it("accepts distinct real rejection and acceptance branches after an explicit changed request", () => expect(gradeGovernedHire(valid()).passed).toBe(true));
it("accepts natural phase-specific proposal language", () => { const o = valid(); o.state.firstReply = "The board must approve Morgan's QA hire proposal before work can begin."; o.state.secondReply = "Jules's replacement proposal is pending the board's approval decision."; expect(gradeGovernedHire(o).passed).toBe(true); });
it("rejects missing governance evidence", () => expect(gradeGovernedHire(undefined).passed).toBe(false));
it("rejects a working employee before the decision", () => { const o = valid(); o.state.noWorkerBeforeFirstDecision = false; expect(gradeGovernedHire(o).passed).toBe(false); });
it("rejects repeating the rejected proposal without changed human direction", () => { const o = valid(); o.state.noRepeatedProposalBeforeChangedRequest = false; expect(gradeGovernedHire(o).passed).toBe(false); });
it("rejects accepting a replacement identity instead of the proposed hire", () => { const o = valid(); o.agents[0]!.id = "replacement"; expect(gradeGovernedHire(o).passed).toBe(false); });
it("rejects readiness language before human approval", () => { const o = valid(); o.state.firstReply = "Morgan is now ready and working."; expect(gradeGovernedHire(o).passed).toBe(false); });
it("rejects a hidden nudge classified as a decision notification", () => { const o = valid(); o.runs.push({ id: "extra", agentId: "ceo", status: "succeeded", contextSnapshot: { source: "approval.approved", approvalId: "foreign" } }); expect(gradeGovernedHire(o).passed).toBe(false); });
it("accepts a separately counted exact approval notification", () => { const o = valid(); o.runs.push({ id: "extra", agentId: "ceo", status: "succeeded", contextSnapshot: { source: "approval.approved", approvalId: "second" } }); expect(gradeGovernedHire(o).passed).toBe(true); });
it("accepts the retained request-ready answer with an actual pending proposal and explicit activation gate", () => {
const o = valid(); o.state.firstReply = "Morgan’s QA Engineer hire request is ready. Morgan will report to the CEO. Approve Morgan’s hire to activate the agent.";
expect(gradeGovernedHire(o).passed).toBe(true);
});
it("rejects pending language mixed with a named employee readiness claim", () => {
const o = valid(); o.state.firstReply = "The proposal is pending, but Morgan is now ready and working.";
expect(gradeGovernedHire(o).passed).toBe(false);
o.state.firstReply = "Approve the proposal; the QA engineer is active."; expect(gradeGovernedHire(o).passed).toBe(false);
});