Codemod db pass-through calls: messages + runs + approvals + company (C1 part 2/3)

Rewrite ~376 call sites for messages, runs, approvalsMod, and company
domains and delete the corresponding pass-through methods on
AppDatabase / AppDatabaseBase. Structural type references
(ReturnType<HandlerDeps["db"]["getRun"]>) and SweepStaleReviewsDeps-style
mocks are updated to route through the owning sub-module.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 13:20:15 -04:00
1 parent 5e9b7acbc6
commit a69fbb053b
86 files changed
+393 -454

No files matched your search

+1 -1
View File
@@ -22,7 +22,7 @@ describe("agent budget policy synchronization", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Budget Sync Co",
description: "Budget sync regression coverage",
status: "active",
+1 -1
View File
@@ -23,7 +23,7 @@ describe("hire routing guards", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Routing Co",
description: "Hire routing regression coverage",
status: "active",
+3 -3
View File
@@ -30,7 +30,7 @@ describe("canManageOrganization", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Org Permissions Co",
description: "Tests recursive org authority",
status: "active",
@@ -100,7 +100,7 @@ describe("canManageOrganization", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Org Permission Override Co",
description: "Tests permission-based org authority",
status: "active",
@@ -154,7 +154,7 @@ describe("canManageOrganization", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Scoped Authority Co",
description: "Tests that branch growth does not unlock org-wide admin powers",
status: "active",
+2 -2
View File
@@ -31,7 +31,7 @@ describe("hire approval routing", () => {
lastError: null,
});
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Hire Routing Co",
description: "Tests recursive hire wake routing",
status: "active",
@@ -91,7 +91,7 @@ describe("hire approval routing", () => {
payloadJson: "{}",
});
db.decideApproval({
db.approvalsMod.decideApproval({
approvalId,
state: "approved",
decisionNote: "Approved by board",
@@ -31,7 +31,7 @@ describe("deliverable review feedback writeback", () => {
lastError: null,
});
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Review Feedback Co",
description: "Tests review feedback knowledge writeback",
status: "active",
@@ -75,7 +75,7 @@ describe("deliverable review feedback writeback", () => {
authorAgentId: agentId,
status: "in_review",
});
const approvalId = db.requestApproval({
const approvalId = db.approvalsMod.requestApproval({
companyId,
relatedTaskId: taskId,
requestedByAgentId: agentId,
@@ -85,7 +85,7 @@ describe("deliverable review feedback writeback", () => {
payloadJson: JSON.stringify({ documentIds: [documentId] }),
});
db.decideApproval({
db.approvalsMod.decideApproval({
approvalId,
state: "revision_requested",
decisionNote: "Add stronger competitor evidence and a clearer recommendation.",
+22 -22
View File
@@ -28,7 +28,7 @@ type RawDb = {
// ---------------------------------------------------------------------------
function createTestCompany(db: AppDatabase): string {
return db.saveCompany({
return db.company.saveCompany({
name: "Test Company",
description: "Atomic checkout tests",
status: "active",
@@ -109,7 +109,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -131,14 +131,14 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId1 } = db.createRun({
const { id: runId1 } = db.runs.createRun({
companyId,
taskId,
agentId,
workspaceId,
connectorId: "openai-codex",
});
const { id: runId2 } = db.createRun({
const { id: runId2 } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -160,7 +160,7 @@ describe("CAS checkout", () => {
// Manually set task to in_progress
(db as unknown as RawDb).db.prepare("UPDATE tasks SET status = 'in_progress' WHERE id = ?").run(taskId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -178,7 +178,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -187,8 +187,8 @@ describe("CAS checkout", () => {
});
db.tasks.checkoutTask(taskId, runId);
db.markRunStatus(runId, "running", "");
db.finishRun({
db.runs.markRunStatus(runId, "running", "");
db.runs.finishRun({
runId,
status: "succeeded",
summary: "Done",
@@ -214,7 +214,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -223,7 +223,7 @@ describe("CAS checkout", () => {
});
db.tasks.checkoutTask(taskId, runId);
db.markRunStatus(runId, "running", "");
db.runs.markRunStatus(runId, "running", "");
// Deleting the agent triggers cancelRunForDeletion for active runs
db.agents.deleteAgent(agentId, companyId);
@@ -243,7 +243,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -283,7 +283,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -316,7 +316,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -328,7 +328,7 @@ describe("CAS checkout", () => {
// Never call markRunStatus('running', ...) — this simulates the
// "workspace already locked" bail-out inside dispatchRunToWorker.
db.finishRun({
db.runs.finishRun({
runId,
status: "failed",
summary: null,
@@ -343,7 +343,7 @@ describe("CAS checkout", () => {
// And the next CAS checkout must succeed — proving the heartbeat
// retry path is unblocked.
const { id: retryRunId } = db.createRun({
const { id: retryRunId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -364,7 +364,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -372,7 +372,7 @@ describe("CAS checkout", () => {
connectorId: "openai-codex",
});
db.tasks.checkoutTask(taskId, runId);
db.finishRun({
db.runs.finishRun({
runId,
status: "cancelled",
summary: null,
@@ -397,7 +397,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: runId } = db.createRun({
const { id: runId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -405,8 +405,8 @@ describe("CAS checkout", () => {
connectorId: "openai-codex",
});
db.tasks.checkoutTask(taskId, runId);
db.markRunStatus(runId, "running", "");
db.finishRun({
db.runs.markRunStatus(runId, "running", "");
db.runs.finishRun({
runId,
status: "failed",
summary: null,
@@ -465,7 +465,7 @@ describe("CAS checkout", () => {
const agentId = createTestAgent(db, companyId, workspaceId);
const taskId = createTestTask(db, companyId, null, workspaceId);
const { id: liveRunId } = db.createRun({
const { id: liveRunId } = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -473,7 +473,7 @@ describe("CAS checkout", () => {
connectorId: "openai-codex",
});
db.tasks.checkoutTask(taskId, liveRunId);
db.markRunStatus(liveRunId, "running", "");
db.runs.markRunStatus(liveRunId, "running", "");
db.close();
db = new AppDatabase(tempDir);
+5 -5
View File
@@ -40,7 +40,7 @@ describe("company mode switching", () => {
lastError: null,
});
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Mode Switch Co",
description: "Execution mode cleanup",
status: "active",
@@ -101,7 +101,7 @@ describe("company mode switching", () => {
threadIntegration.onTaskCreated(taskId, companyId);
threadIntegration.onRunFinished("run-1", taskId, engineerId, companyId, "succeeded", null);
db.tasks.setTaskRequiresUserReview(taskId, true);
const approvalId = db.requestApproval({
const approvalId = db.approvalsMod.requestApproval({
companyId,
relatedTaskId: taskId,
requestedByAgentId: engineerId,
@@ -114,7 +114,7 @@ describe("company mode switching", () => {
expect(db.listThreadWaitStates(companyId).length).toBeGreaterThan(0);
expect(db.entityCrud.getTask(taskId).requiresUserReview).toBe(true);
expect(db.getApprovalRecord(approvalId).state).toBe("pending");
expect(db.approvalsMod.getApprovalRecord(approvalId).state).toBe("pending");
const handlers = new Map<string, IpcHandler>();
registerCoreAdminHandlers({
@@ -147,10 +147,10 @@ describe("company mode switching", () => {
}) as { ok: boolean };
expect(result.ok).toBe(true);
expect(db.getCompanyExecutionMode(companyId)).toBe("ai_ceo");
expect(db.company.getCompanyExecutionMode(companyId)).toBe("ai_ceo");
expect(db.listThreadWaitStates(companyId)).toHaveLength(0);
expect(db.entityCrud.getTask(taskId).requiresUserReview).toBe(false);
expect(db.getApprovalRecord(approvalId).state).toBe("approved");
expect(db.approvalsMod.getApprovalRecord(approvalId).state).toBe("approved");
db.close();
});
+29 -29
View File
@@ -34,7 +34,7 @@ describe("AppDatabase", () => {
});
it("persists company-scoped entities and resolves secret env bindings", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Northline Systems",
description: "Operator company",
status: "active",
@@ -115,7 +115,7 @@ describe("AppDatabase", () => {
});
it("backs up and restores the profile", async () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Backup Test Co",
description: "Backup validation company",
status: "active",
@@ -123,7 +123,7 @@ describe("AppDatabase", () => {
const backupDir = await mkdtemp(join(tmpdir(), "agentcompany-backup-"));
await db.exportBackup(backupDir);
db.saveCompany({
db.company.saveCompany({
id: companyId,
name: "Mutated Company",
description: "Changed after backup",
@@ -139,12 +139,12 @@ describe("AppDatabase", () => {
});
it("scopes secret resolution to the owning company", () => {
const alphaCompanyId = db.saveCompany({
const alphaCompanyId = db.company.saveCompany({
name: "Alpha Company",
description: "Alpha",
status: "active",
});
const betaCompanyId = db.saveCompany({
const betaCompanyId = db.company.saveCompany({
name: "Beta Company",
description: "Beta",
status: "active",
@@ -168,7 +168,7 @@ describe("AppDatabase", () => {
});
it("atomically checks out unclaimed work via CAS with run ID", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Checkout Company",
description: "Atomic checkout validation",
status: "active",
@@ -210,14 +210,14 @@ describe("AppDatabase", () => {
status: "todo",
});
const { id: runId1 } = db.createRun({
const { id: runId1 } = db.runs.createRun({
companyId,
taskId,
agentId: leadId,
workspaceId,
connectorId: "openai-codex",
});
const { id: runId2 } = db.createRun({
const { id: runId2 } = db.runs.createRun({
companyId,
taskId,
agentId: leadId,
@@ -233,7 +233,7 @@ describe("AppDatabase", () => {
});
it("auto-pauses an agent when a run exhausts the monthly budget", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Budget Company",
description: "Budget hard stop validation",
status: "active",
@@ -269,7 +269,7 @@ describe("AppDatabase", () => {
status: "todo",
});
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -278,7 +278,7 @@ describe("AppDatabase", () => {
});
// Simulate a per-message cost entry (written by CostWriter in prod).
db.recordCostEntry({
db.runs.recordCostEntry({
runId: run.id,
companyId,
agentId,
@@ -288,7 +288,7 @@ describe("AppDatabase", () => {
unattributed: false,
});
const outcome = db.finishRun({
const outcome = db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Budget consumed",
@@ -305,7 +305,7 @@ describe("AppDatabase", () => {
});
it("activates pending hires when the corresponding approval is granted", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Hiring Company",
description: "Approval-driven hiring",
status: "active",
@@ -337,7 +337,7 @@ describe("AppDatabase", () => {
budgetMonthlyUsd: 50,
});
const approvalId = db.requestApproval({
const approvalId = db.approvalsMod.requestApproval({
companyId,
relatedTaskId: null,
requestedByAgentId: managerId,
@@ -347,7 +347,7 @@ describe("AppDatabase", () => {
payloadJson: JSON.stringify({ agentId: pendingHireId }),
});
db.decideApproval({
db.approvalsMod.decideApproval({
approvalId,
state: "approved",
decisionNote: "Approved",
@@ -357,7 +357,7 @@ describe("AppDatabase", () => {
});
it("detects pending-approval agents via isAgentPendingApproval", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Gate Test Co",
description: "Approval gate validation",
status: "active",
@@ -408,7 +408,7 @@ describe("AppDatabase", () => {
});
it("acquires and releases workspace locks", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Lock Test Co",
description: "Workspace lock test",
status: "active",
@@ -444,7 +444,7 @@ describe("AppDatabase", () => {
});
it("releases all workspace locks on crash recovery", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Recovery Co",
description: "Lock recovery test",
status: "active",
@@ -466,7 +466,7 @@ describe("AppDatabase", () => {
});
it("purges expired run logs based on retention setting", async () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Purge Co",
description: "Log purge test",
status: "active",
@@ -502,11 +502,11 @@ describe("AppDatabase", () => {
status: "todo",
});
const run = db.createRun({ companyId, taskId, agentId, workspaceId: wsId, connectorId: "openai-codex" });
await db.appendRunLog(run.id, "stdout", "test log line\n");
const run = db.runs.createRun({ companyId, taskId, agentId, workspaceId: wsId, connectorId: "openai-codex" });
await db.runs.appendRunLog(run.id, "stdout", "test log line\n");
// Finish the run with a very old timestamp
db.finishRun({
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "done",
@@ -518,7 +518,7 @@ describe("AppDatabase", () => {
});
// Log should exist before purge
expect(db.readRunLog(run.id)).toContain("test log line");
expect(db.runs.readRunLog(run.id)).toContain("test log line");
// Set retention to 1 day and manually backdate the run's finished_at
db.updateSettings({ logRetentionDays: 1 });
@@ -533,11 +533,11 @@ describe("AppDatabase", () => {
expect(purged).toBe(1);
// Log should be gone after purge
expect(db.readRunLog(run.id)).toBe("");
expect(db.runs.readRunLog(run.id)).toBe("");
});
it("populates related_agent_id on hire approvals", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Agent Approval Co",
description: "test",
status: "active",
@@ -569,7 +569,7 @@ describe("AppDatabase", () => {
budgetMonthlyUsd: 50,
});
const approvalId = db.requestApproval({
const approvalId = db.approvalsMod.requestApproval({
companyId,
requestedByAgentId: managerId,
type: "hire_agent",
@@ -578,12 +578,12 @@ describe("AppDatabase", () => {
payloadJson: JSON.stringify({ agentId: hireId }),
});
const approval = db.getApprovalRecord(approvalId);
const approval = db.approvalsMod.getApprovalRecord(approvalId);
// related_agent_id should be populated from payloadJson extraction
expect(approval.relatedAgentId).toBe(hireId);
// Explicit relatedAgentId param should also work
const approvalId2 = db.requestApproval({
const approvalId2 = db.approvalsMod.requestApproval({
companyId,
requestedByAgentId: managerId,
relatedAgentId: hireId,
@@ -592,7 +592,7 @@ describe("AppDatabase", () => {
impactSummary: "test",
});
const approval2 = db.getApprovalRecord(approvalId2);
const approval2 = db.approvalsMod.getApprovalRecord(approvalId2);
expect(approval2.relatedAgentId).toBe(hireId);
});
+30 -30
View File
@@ -20,7 +20,7 @@ import { createBudgetEnforcementService } from "../../src/main/budget-enforcemen
// ---------------------------------------------------------------------------
function scaffold(db: AppDatabase) {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Budget Edge Case Co",
description: "Budget exhaustion mid-run edge case tests (D-05.2)",
status: "active",
@@ -128,7 +128,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
});
// Start Run-1 (the in-flight run)
const run1 = db.createRun({
const run1 = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -136,7 +136,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId, run1.id);
db.markRunStatus(run1.id, "running", "");
db.runs.markRunStatus(run1.id, "running", "");
// Create a second task and run that exhausts budget WHILE Run-1 is in-flight
const taskId2 = db.tasks.saveTask({
@@ -148,7 +148,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
priority: "medium",
status: "todo",
});
const run0 = db.createRun({
const run0 = db.runs.createRun({
companyId,
taskId: taskId2,
agentId,
@@ -156,10 +156,10 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId2, run0.id);
db.markRunStatus(run0.id, "running", "");
db.runs.markRunStatus(run0.id, "running", "");
// Complete Run-0 with $6 cost (exceeds $5 budget)
db.recordCostEntry({ runId: run0.id, companyId, agentId, taskId: taskId2, connectorId: "gemini-cli", amountUsd: 6.0, unattributed: false });
db.finishRun({
db.runs.recordCostEntry({ runId: run0.id, companyId, agentId, taskId: taskId2, connectorId: "gemini-cli", amountUsd: 6.0, unattributed: false });
db.runs.finishRun({
runId: run0.id,
status: "succeeded",
summary: "Expensive run",
@@ -172,8 +172,8 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
// Now complete Run-1 (the in-flight run) -- it should succeed normally
// Per D-04/D-05: in-flight runs are unaffected by budget exhaustion
db.recordCostEntry({ runId: run1.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 0.5, unattributed: false });
db.finishRun({
db.runs.recordCostEntry({ runId: run1.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 0.5, unattributed: false });
db.runs.finishRun({
runId: run1.id,
status: "succeeded",
summary: "In-flight run completed",
@@ -185,7 +185,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
});
// Verify Run-1 completed successfully
const finishedRun = db.getRun(run1.id);
const finishedRun = db.runs.getRun(run1.id);
expect(finishedRun.status).toBe("succeeded");
// Verify Run-1's cost was recorded (total spend now $6.50)
@@ -214,7 +214,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
});
// Complete a run that exceeds budget
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -222,9 +222,9 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId, run.id);
db.markRunStatus(run.id, "running", "");
db.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 6.0, unattributed: false });
db.finishRun({
db.runs.markRunStatus(run.id, "running", "");
db.runs.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 6.0, unattributed: false });
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Done",
@@ -262,7 +262,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
});
// Exhaust budget
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -270,9 +270,9 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId, run.id);
db.markRunStatus(run.id, "running", "");
db.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 6.0, unattributed: false });
db.finishRun({
db.runs.markRunStatus(run.id, "running", "");
db.runs.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 6.0, unattributed: false });
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Done",
@@ -319,7 +319,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
});
// Complete a run costing $1.50 (150 cents > 100 agent limit)
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -327,9 +327,9 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId, run.id);
db.markRunStatus(run.id, "running", "");
db.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 1.5, unattributed: false });
db.finishRun({
db.runs.markRunStatus(run.id, "running", "");
db.runs.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 1.5, unattributed: false });
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Done",
@@ -371,7 +371,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
expect(before.allowed).toBe(true);
// Complete a run costing $4 (400 cents > 300 limit)
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -379,9 +379,9 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId, run.id);
db.markRunStatus(run.id, "running", "");
db.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 4.0, unattributed: false });
db.finishRun({
db.runs.markRunStatus(run.id, "running", "");
db.runs.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 4.0, unattributed: false });
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Done",
@@ -417,7 +417,7 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
});
// Run that will exceed budget on completion
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
@@ -425,11 +425,11 @@ describe("Edge Case: Budget Exhaustion Mid-Run (D-05.2)", () => {
connectorId: "gemini-cli",
});
db.tasks.checkoutTask(taskId, run.id);
db.markRunStatus(run.id, "running", "");
db.runs.markRunStatus(run.id, "running", "");
// Complete with cost that exceeds budget -- cost entry is still recorded
db.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 5.0, unattributed: false });
db.finishRun({
db.runs.recordCostEntry({ runId: run.id, companyId, agentId, taskId, connectorId: "gemini-cli", amountUsd: 5.0, unattributed: false });
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Done",
+13 -13
View File
@@ -28,7 +28,7 @@ type RawDb = {
// ---------------------------------------------------------------------------
function createTestCompany(db: AppDatabase): string {
return db.saveCompany({
return db.company.saveCompany({
name: "Edge Case Company",
description: "Concurrent checkout edge case tests (D-05.1)",
status: "active",
@@ -110,14 +110,14 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
const agentB = createTestAgent(db, companyId, workspaceId, "Agent-B");
const taskId = createTestTask(db, companyId, workspaceId);
const { id: runIdA } = db.createRun({
const { id: runIdA } = db.runs.createRun({
companyId,
taskId,
agentId: agentA,
workspaceId,
connectorId: "gemini-cli",
});
const { id: runIdB } = db.createRun({
const { id: runIdB } = db.runs.createRun({
companyId,
taskId,
agentId: agentB,
@@ -146,14 +146,14 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
const agentB = createTestAgent(db, companyId, workspaceId, "Agent-B");
const taskId1 = createTestTask(db, companyId, workspaceId);
const { id: runIdA } = db.createRun({
const { id: runIdA } = db.runs.createRun({
companyId,
taskId: taskId1,
agentId: agentA,
workspaceId,
connectorId: "gemini-cli",
});
const { id: runIdB1 } = db.createRun({
const { id: runIdB1 } = db.runs.createRun({
companyId,
taskId: taskId1,
agentId: agentB,
@@ -168,7 +168,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
// Agent-B can still checkout a DIFFERENT task
const taskId2 = createTestTask(db, companyId, workspaceId);
const { id: runIdB2 } = db.createRun({
const { id: runIdB2 } = db.runs.createRun({
companyId,
taskId: taskId2,
agentId: agentB,
@@ -192,7 +192,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
const taskId = createTestTask(db, companyId, workspaceId);
// Agent-A checks out successfully
const { id: runIdA } = db.createRun({
const { id: runIdA } = db.runs.createRun({
companyId,
taskId,
agentId: agentA,
@@ -202,7 +202,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
expect(db.tasks.checkoutTask(taskId, runIdA)).toBe(true);
// Task is now in_progress. A new run from Agent-B tries to checkout
const { id: runIdB } = db.createRun({
const { id: runIdB } = db.runs.createRun({
companyId,
taskId,
agentId: agentB,
@@ -225,7 +225,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
const taskId = createTestTask(db, companyId, workspaceId);
// Agent-A checks out task
const { id: runIdA } = db.createRun({
const { id: runIdA } = db.runs.createRun({
companyId,
taskId,
agentId: agentA,
@@ -246,7 +246,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
// Task is still in_progress though, so a new checkout fails
// (CAS checks status IN ('todo', 'backlog'))
const { id: runIdB } = db.createRun({
const { id: runIdB } = db.runs.createRun({
companyId,
taskId,
agentId: agentB,
@@ -264,7 +264,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
const agentA = createTestAgent(db, companyId, workspaceId, "Agent-A");
const taskId = createTestTask(db, companyId, workspaceId);
const { id: runIdA } = db.createRun({
const { id: runIdA } = db.runs.createRun({
companyId,
taskId,
agentId: agentA,
@@ -300,7 +300,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
const taskId = createTestTask(db, companyId, workspaceId);
// Agent-A checks out, then lock goes stale
const { id: runIdA } = db.createRun({
const { id: runIdA } = db.runs.createRun({
companyId,
taskId,
agentId: agentA,
@@ -322,7 +322,7 @@ describe("Edge Case: Concurrent Task Checkout (D-05.1)", () => {
expect(db.entityCrud.getTask(taskId).status).toBe("todo");
// Agent-B can now checkout the recovered task
const { id: runIdB } = db.createRun({
const { id: runIdB } = db.runs.createRun({
companyId,
taskId,
agentId: agentB,
+5 -5
View File
@@ -21,7 +21,7 @@ import type { ConnectorId } from "@shared/types";
// ---------------------------------------------------------------------------
function scaffold(db: AppDatabase, connectorId: ConnectorId = "gemini-cli") {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Session Edge Case Co",
description: "Session rotation edge case tests (D-05.3)",
status: "active",
@@ -175,14 +175,14 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
}
// Create a completed run for history (so generateHandoff has run data)
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
workspaceId,
connectorId: "gemini-cli" as ConnectorId,
});
db.finishRun({
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Completed initial implementation",
@@ -305,14 +305,14 @@ describe("Edge Case: Session Rotation During Execution (D-05.3)", () => {
db.tasks.incrementSessionUsage(sessionId, 300000, 200000, "run-1");
// Create a completed run for run history
const run = db.createRun({
const run = db.runs.createRun({
companyId,
taskId,
agentId,
workspaceId,
connectorId: "gemini-cli" as ConnectorId,
});
db.finishRun({
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Previous work done",
+1 -1
View File
@@ -38,7 +38,7 @@ describe("ipc-core-agent-graph-handlers model enforcement", () => {
version: "test",
lastError: null,
});
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Handler Test Co",
description: "Tests saveAgent model validation",
status: "active",
+1 -1
View File
@@ -22,7 +22,7 @@ describe("knowledge provenance", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Knowledge Provenance Co",
description: "Tests sourceRunId updates on knowledge entry edits",
status: "active",
+5 -5
View File
@@ -27,7 +27,7 @@ function createScaffold(db: AppDatabase) {
lastError: null,
});
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Message Dispatch Co",
description: "Tests board wake and wait-state resolution",
status: "active",
@@ -191,9 +191,9 @@ describe("message dispatch", () => {
if (!result.ok) throw new Error("Expected dispatch to succeed.");
expect(new Set(result.data.wakeTargets)).toEqual(new Set([ceoId, ctoId]));
const ceoInbox = db.listAgentInboxUnread(companyId, ceoId);
const ceoInbox = db.messages.listAgentInboxUnread(companyId, ceoId);
expect(ceoInbox.map((entry) => entry.id)).toContain(result.data.id);
const ctoInbox = db.listAgentInboxUnread(companyId, ctoId);
const ctoInbox = db.messages.listAgentInboxUnread(companyId, ctoId);
expect(ctoInbox.map((entry) => entry.id)).toContain(result.data.id);
db.close();
@@ -230,9 +230,9 @@ describe("message dispatch", () => {
// The message is still visible to CTO's inbox — they were the
// addressed recipient — but CTO is not required to answer.
const ctoInbox = db.listAgentInboxUnread(companyId, ctoId);
const ctoInbox = db.messages.listAgentInboxUnread(companyId, ctoId);
expect(ctoInbox.map((entry) => entry.id)).toContain(result.data.id);
const ceoInbox = db.listAgentInboxUnread(companyId, ceoId);
const ceoInbox = db.messages.listAgentInboxUnread(companyId, ceoId);
expect(ceoInbox.map((entry) => entry.id)).toContain(result.data.id);
db.close();
+18 -18
View File
@@ -26,7 +26,7 @@ describe("AppDatabase.searchMessages", () => {
db = new AppDatabase(tempDir);
db.init();
companyId = db.saveCompany({
companyId = db.company.saveCompany({
name: "Search Test Corp",
description: "Company for testing message search",
status: "active",
@@ -61,7 +61,7 @@ describe("AppDatabase.searchMessages", () => {
});
// Seed messages across different channels
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentA,
toAgentId: agentB,
@@ -71,7 +71,7 @@ describe("AppDatabase.searchMessages", () => {
priority: "normal",
});
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentB,
toAgentId: agentA,
@@ -81,7 +81,7 @@ describe("AppDatabase.searchMessages", () => {
priority: "normal",
});
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentA,
channel: "company",
@@ -90,7 +90,7 @@ describe("AppDatabase.searchMessages", () => {
priority: "normal",
});
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentA,
channel: "department",
@@ -100,7 +100,7 @@ describe("AppDatabase.searchMessages", () => {
priority: "urgent",
});
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentB,
channel: "department",
@@ -117,21 +117,21 @@ describe("AppDatabase.searchMessages", () => {
});
it("returns messages where body contains the query string", () => {
const results = db.searchMessages(companyId, "velocity");
const results = db.messages.searchMessages(companyId, "velocity");
expect(results.length).toBe(1);
expect(results[0].companyId).toBe(companyId);
expect(results[0].body.toLowerCase()).toContain("velocity");
});
it("returns messages where subject contains the query string", () => {
const results = db.searchMessages(companyId, "retrospective");
const results = db.messages.searchMessages(companyId, "retrospective");
expect(results.length).toBe(1);
expect(results[0].subject).toBe("Sprint retrospective");
});
it("escapes LIKE wildcards so % and _ match literally", () => {
// Insert a message with literal % and _ characters
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentA,
channel: "company",
@@ -141,25 +141,25 @@ describe("AppDatabase.searchMessages", () => {
});
// Search for the literal "95%"
const percentResults = db.searchMessages(companyId, "95%");
const percentResults = db.messages.searchMessages(companyId, "95%");
expect(percentResults.length).toBe(1);
expect(percentResults[0].body).toContain("95%");
// Search for the literal "disk_io"
const underscoreResults = db.searchMessages(companyId, "disk_io");
const underscoreResults = db.messages.searchMessages(companyId, "disk_io");
expect(underscoreResults.length).toBe(1);
expect(underscoreResults[0].body).toContain("disk_io");
});
it("scopes to a specific channel when channel param is provided", () => {
const results = db.searchMessages(companyId, "approvals", { channel: "department" });
const results = db.messages.searchMessages(companyId, "approvals", { channel: "department" });
expect(results.length).toBe(1);
expect(results[0].channel).toBe("department");
expect(results[0].body).toContain("approvals");
});
it("scopes to channelTargetId when provided alongside channel", () => {
const results = db.searchMessages(companyId, "updated", {
const results = db.messages.searchMessages(companyId, "updated", {
channel: "department",
channelTargetId: "design",
});
@@ -168,14 +168,14 @@ describe("AppDatabase.searchMessages", () => {
});
it("returns empty array when no matches", () => {
const results = db.searchMessages(companyId, "xyznonexistentquery");
const results = db.messages.searchMessages(companyId, "xyznonexistentquery");
expect(results).toEqual([]);
});
it("respects the limit parameter (default 50)", () => {
// Insert 60 messages
for (let i = 0; i < 60; i++) {
db.sendAgentMessage({
db.messages.sendAgentMessage({
companyId,
fromAgentId: agentA,
channel: "company",
@@ -186,16 +186,16 @@ describe("AppDatabase.searchMessages", () => {
}
// Default limit should be 50
const defaultResults = db.searchMessages(companyId, "flood test");
const defaultResults = db.messages.searchMessages(companyId, "flood test");
expect(defaultResults.length).toBe(50);
// Explicit limit of 10
const limitedResults = db.searchMessages(companyId, "flood test", { limit: 10 });
const limitedResults = db.messages.searchMessages(companyId, "flood test", { limit: 10 });
expect(limitedResults.length).toBe(10);
});
it("returns results ordered by created_at DESC (most recent first)", () => {
const results = db.searchMessages(companyId, "migration");
const results = db.messages.searchMessages(companyId, "migration");
expect(results.length).toBeGreaterThanOrEqual(2);
for (let i = 1; i < results.length; i++) {
+2 -2
View File
@@ -27,7 +27,7 @@ import { resolveWorkspaceWithLockMode } from "../../src/main/orchestration/resol
*/
function seedCompany(db: AppDatabase) {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Parallel Co",
description: "Regression fixture",
status: "active",
@@ -151,7 +151,7 @@ describe("resolveWorkspaceWithLockMode", () => {
});
it("no workspace at all → none", () => {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Empty Co",
description: "",
status: "active",
+7 -7
View File
@@ -21,7 +21,7 @@ import type { ConnectorId, TaskSessionRecord } from "@shared/types";
// Helpers — create a minimal company + agent + task scaffold
// ---------------------------------------------------------------------------
function scaffold(db: AppDatabase) {
const companyId = db.saveCompany({
const companyId = db.company.saveCompany({
name: "Session Test Co",
description: "Testing session management",
status: "active",
@@ -185,8 +185,8 @@ describe("task_sessions CRUD", () => {
const { taskId, companyId, agentId, workspaceId } = scaffold(db);
// Create some runs
const run1 = db.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "claude-pro" });
db.finishRun({
const run1 = db.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "claude-pro" });
db.runs.finishRun({
runId: run1.id,
status: "succeeded",
summary: "First run done",
@@ -197,8 +197,8 @@ describe("task_sessions CRUD", () => {
unattributedCost: false,
});
const run2 = db.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "claude-pro" });
db.finishRun({
const run2 = db.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "claude-pro" });
db.runs.finishRun({
runId: run2.id,
status: "failed",
summary: "Second run failed",
@@ -431,8 +431,8 @@ describe("session management service", () => {
});
// Create a completed run for history
const run = db.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "gemini-cli" as ConnectorId });
db.finishRun({
const run = db.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "gemini-cli" as ConnectorId });
db.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Implemented initial logic",
+11 -7
View File
@@ -22,7 +22,9 @@ describe("sweepStaleReviews", () => {
getManagerForAgent: vi.fn().mockReturnValue(null),
getChainOfCommand: vi.fn().mockReturnValue([]),
},
findPendingApprovalForTask: vi.fn().mockReturnValue(null),
approvalsMod: {
findPendingApprovalForTask: vi.fn().mockReturnValue(null),
},
} as unknown as AppDatabase,
getCompanyExecutionMode: vi.fn().mockReturnValue("ai_ceo"),
dispatchAgentMessage: vi.fn().mockReturnValue({ ok: true }),
@@ -47,7 +49,9 @@ describe("sweepStaleReviews", () => {
getManagerForAgent: ReturnType<typeof vi.fn>;
getChainOfCommand: ReturnType<typeof vi.fn>;
};
findPendingApprovalForTask: ReturnType<typeof vi.fn>;
approvalsMod: {
findPendingApprovalForTask: ReturnType<typeof vi.fn>;
};
};
it("escalates to manager's manager when task in_review for 35 minutes", () => {
@@ -96,7 +100,7 @@ describe("sweepStaleReviews", () => {
dbMock.tasks.listReviewTasksForSweep.mockReturnValueOnce([
{ id: "task-1", assigneeAgentId: "agent-1", updatedAt: THIRTY_FIVE_MIN_AGO, title: "Build login" },
]);
dbMock.findPendingApprovalForTask.mockReturnValueOnce(null);
dbMock.approvalsMod.findPendingApprovalForTask.mockReturnValueOnce(null);
dbMock.agents.getManagerForAgent.mockReturnValueOnce({ id: "ceo-1", name: "CEO", companyId: "company-1" });
dbMock.agents.getChainOfCommand.mockReturnValueOnce([]);
@@ -122,7 +126,7 @@ describe("sweepStaleReviews", () => {
]);
dbMock.agents.getManagerForAgent.mockReturnValueOnce({ id: "manager-1", name: "Manager", companyId: "company-1" });
dbMock.agents.getChainOfCommand.mockReturnValueOnce([{ id: "higher-1", name: "Higher" }]);
dbMock.findPendingApprovalForTask.mockReturnValueOnce({ id: "approval-1", type: "deliverable_review" });
dbMock.approvalsMod.findPendingApprovalForTask.mockReturnValueOnce({ id: "approval-1", type: "deliverable_review" });
sweepStaleReviews("company-1", deps, NOW);
@@ -147,7 +151,7 @@ describe("sweepStaleReviews", () => {
]);
dbMock.agents.getManagerForAgent.mockReturnValueOnce({ id: "manager-1", name: "Manager", companyId: "company-1" });
dbMock.agents.getChainOfCommand.mockReturnValueOnce([{ id: "higher-1", name: "Higher" }]);
dbMock.findPendingApprovalForTask.mockReturnValueOnce({ id: "approval-1", type: "deliverable_review" });
dbMock.approvalsMod.findPendingApprovalForTask.mockReturnValueOnce({ id: "approval-1", type: "deliverable_review" });
(deps.resolveApprovalDecision as ReturnType<typeof vi.fn>).mockImplementationOnce(() => {
throw new Error("Approval already decided");
});
@@ -164,7 +168,7 @@ describe("sweepStaleReviews", () => {
]);
dbMock.agents.getManagerForAgent.mockReturnValueOnce({ id: "manager-1", name: "Manager", companyId: "company-1" });
dbMock.agents.getChainOfCommand.mockReturnValueOnce([{ id: "higher-1", name: "Higher" }]);
dbMock.findPendingApprovalForTask.mockReturnValueOnce(null);
dbMock.approvalsMod.findPendingApprovalForTask.mockReturnValueOnce(null);
sweepStaleReviews("company-1", deps, NOW);
@@ -221,7 +225,7 @@ describe("sweepStaleReviews", () => {
dbMock.tasks.listReviewTasksForSweep.mockReturnValueOnce([
{ id: "task-1", assigneeAgentId: "agent-1", updatedAt: THIRTY_FIVE_MIN_AGO, title: "Review me" },
]);
dbMock.findPendingApprovalForTask.mockReturnValueOnce({ id: "approval-1", type: "deliverable_review" });
dbMock.approvalsMod.findPendingApprovalForTask.mockReturnValueOnce({ id: "approval-1", type: "deliverable_review" });
dbMock.agents.getManagerForAgent.mockReturnValueOnce({ id: "manager-1", name: "Manager", companyId: "company-1" });
const count = sweepStaleReviews("company-1", deps, NOW);
+2 -2
View File
@@ -27,7 +27,7 @@ import { AppDatabase } from "../../src/main/database";
*/
function createTestCompany(db: AppDatabase): string {
return db.saveCompany({
return db.company.saveCompany({
name: "Phase Helper Company",
description: "B2 phase + lease unit tests",
status: "active",
@@ -94,7 +94,7 @@ function createTestRun(
agentId: string,
workspaceId: string,
): string {
const { id } = db.createRun({
const { id } = db.runs.createRun({
companyId,
taskId,
agentId,
+1 -1
View File
@@ -19,7 +19,7 @@ import { AppDatabase } from "../../src/main/database";
// ---------------------------------------------------------------------------
function createTestCompany(db: AppDatabase): string {
return db.saveCompany({
return db.company.saveCompany({
name: "Wakeup Test Company",
description: "Wakeup lifecycle tests",
status: "active",