Q106: a hire awaiting approval is not on staff until approved, and a declined hire leaves

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-08 17:24:31 -04:00
1 parent 170b977bf8
commit c695fdb0f6
11 files changed
+115 -37

No files matched your search

+1 -1
View File
@@ -771,7 +771,7 @@ describe("chat governance", () => {
organization.createAgent({ orgId, name: "Ada", role: "Reviewer", department: "Engineering", modelProviderId: null, modelId: null, budgetCents: 10000, managerAgentId: null });
// The front door refuses duplicate names outright...
expect(() => organization.createAgent({ orgId, name: "ada", role: "Release lead", department: "Engineering", modelProviderId: null, modelId: null, budgetCents: 10000, managerAgentId: null }))
.toThrow("already exists");
.toThrow("is already on staff or awaiting approval");
// ...but a legacy database may already carry duplicates; mentions must
// still refuse to guess between them.
const secondId = organization.createAgent({ orgId, name: "Ada Backup", role: "Release lead", department: "Engineering", modelProviderId: null, modelId: null, budgetCents: 10000, managerAgentId: null });
+40
View File
@@ -7,6 +7,9 @@ import { DatabaseConnection } from "../../src/main/database/connection";
import { OrganizationService } from "../../src/main/services/organization-service";
import { ChatService } from "../../src/main/services/chat-service";
import { dispatchAgentTool, type AgentToolContext } from "../../src/main/services/agent-tools";
import { ApprovalService } from "../../src/main/services/approval-service";
import { requireAssignedAgent } from "../../src/main/services/task-run-preparation";
import type { TaskExecutionTaskRow } from "../../src/main/services/task-prompts";
function call(name: string, args: Record<string, unknown>) {
return { id: `call_${randomUUID()}`, name, arguments: args };
@@ -113,4 +116,41 @@ describe("execution modes", () => {
).get(ceoMode.orgId) as { state: string };
expect(cleared.state).toBe("approved");
});
test("a hire held for review is not on staff until approved, and a declined one never is", () => {
const h = harness("ai_cofounder");
const db = h.connection.db;
const providerId = (db.prepare("select id from providers where org_id = ? and provider_key = 'openai'").get(h.orgId) as { id: string }).id;
const hire = (name: string) => h.connection.transaction(() => h.deps.organization.createAgent({
orgId: h.orgId, name, role: "Designer", department: "Product",
modelProviderId: providerId, modelId: "gpt-5.4", budgetCents: 600000, managerAgentId: h.ceoId,
}));
const lifecycle = (id: string) => (db.prepare("select lifecycle from agents where id = ?").get(id) as { lifecycle: string }).lifecycle;
const identities = (id: string) => (db.prepare("select count(*) as n from service_identities where agent_id = ?").get(id) as { n: number }).n;
const memberships = (id: string) => (db.prepare("select count(*) as n from chat_memberships where principal_type = 'agent' and principal_id = ?").get(id) as { n: number }).n;
const runAs = (id: string) => requireAssignedAgent(db, h.orgId, { assignee_agent_id: id } as TaskExecutionTaskRow);
const approvalOf = (name: string) => (db.prepare("select id from approvals where org_id = ? and kind = 'agent_hire' and title = ?").get(h.orgId, `Review hire: ${name}`) as { id: string }).id;
const employeeId = (db.prepare("select id from employees where org_id = ?").get(h.orgId) as { id: string }).id;
const approvals = new ApprovalService(db);
const ava = hire("Ava");
expect([lifecycle(ava), identities(ava), memberships(ava)]).toEqual(["pending_hire", 0, 0]);
expect(() => runAs(ava)).toThrow("Ava is not hired yet: the hire awaits approval.");
expect(() => hire("ava")).toThrow('An agent named "ava" is already on staff or awaiting approval. Pick a different name.');
const channel = h.connection.transaction(() => h.deps.chat.createSpace({ orgId: h.orgId, name: "design", topic: "t", spaceType: "project", visibility: "workspace" }));
expect(memberships(ava)).toBe(0);
expect(() => h.connection.transaction(() => h.deps.chat.createSpace({ orgId: h.orgId, name: "ava-room", topic: "t", spaceType: "project", visibility: "restricted", memberAgentIds: [ava] })))
.toThrow("Ava is not on staff, so cannot join a channel.");
expect(channel).toBeTruthy();
h.connection.transaction(() => approvals.decide({ orgId: h.orgId, approvalId: approvalOf("Ava"), state: "approved", decidedByEmployeeId: employeeId }));
expect(lifecycle(ava)).toBe("active");
expect(identities(ava)).toBe(1);
expect(memberships(ava)).toBeGreaterThan(0);
expect(runAs(ava).id).toBe(ava);
const bo = hire("Bo");
h.connection.transaction(() => approvals.decide({ orgId: h.orgId, approvalId: approvalOf("Bo"), state: "declined", decidedByEmployeeId: employeeId }));
expect([lifecycle(bo), identities(bo), memberships(bo)]).toEqual(["declined", 0, 0]);
expect(() => runAs(bo)).toThrow("Bo's hire was declined; reassign the task.");
});
});
+2 -2
View File
@@ -74,12 +74,12 @@ describe("identity editing", () => {
expect(() => h.organization.createAgent({
orgId: h.orgId, name: "dana lee", role: "Designer", department: "Design",
modelProviderId: null, modelId: null, budgetCents: 1000, managerAgentId: h.agentId,
})).toThrow("already exists");
})).toThrow("is already on staff or awaiting approval");
// Renaming the CEO onto that name is equally ambiguous.
expect(() => h.organization.updateAgent({
orgId: h.orgId, agentId: h.agentId, name: "Dana Lee", role: "CEO", title: "CEO",
roleLevel: "c_suite", department: "Executive", budgetCents: 25000, modelProviderId: null, modelId: null,
})).toThrow("already exists");
})).toThrow("is already on staff or awaiting approval");
// Saving without changing the name stays legal.
h.connection.transaction(() => h.organization.updateAgent({
orgId: h.orgId, agentId: h.agentId, name: "CEO", role: "CEO", title: "CEO",
+4
View File
@@ -31,6 +31,10 @@ describe("staffing limits on edits", () => {
connection.db.prepare("update hiring_policies set monthly_budget_limit_cents = 100 where org_id = ? and department_name = 'Sales'").run(orgId);
edit("Sales", 2000);
expect(connection.db.prepare("select department, budget_cents from agents where id = ?").get(sam)).toEqual({ department: "Sales", budget_cents: 2000 });
// A hire awaiting approval already holds its place in the department.
connection.db.prepare("update agents set department = 'Sales' where name = 'Dee'").run();
connection.db.prepare("insert into agents(id, org_id, name, role, department, budget_cents, lifecycle, created_at) values ('agt_pending', ?, 'Pat', 'Staff', 'Design', 1000, 'pending_hire', ?)").run(orgId, new Date().toISOString());
expect(() => edit("Design", 1000)).toThrow("Design is at its headcount limit (1).");
connection.close();
});
});