diff --git a/src/main/agent-runtime/cost-writer.ts b/src/main/agent-runtime/cost-writer.ts index 5d107b51..24f019c5 100644 --- a/src/main/agent-runtime/cost-writer.ts +++ b/src/main/agent-runtime/cost-writer.ts @@ -45,7 +45,7 @@ export class CostWriter { ); } - this.deps.db.recordCostEntry({ + this.deps.db.runs.recordCostEntry({ runId: input.runId, companyId: input.companyId, agentId: input.agentId, diff --git a/src/main/agent-runtime/hook-handlers.ts b/src/main/agent-runtime/hook-handlers.ts index 66c06399..0395bf82 100644 --- a/src/main/agent-runtime/hook-handlers.ts +++ b/src/main/agent-runtime/hook-handlers.ts @@ -134,7 +134,7 @@ function checkOperationalApprovalBlock( toolName: string, ): BeforeToolCallRpcResult { try { - const blocking = deps.db.getBlockingApproval(ctx.companyId, ctx.agentId, ctx.taskId); + const blocking = deps.db.approvalsMod.getBlockingApproval(ctx.companyId, ctx.agentId, ctx.taskId); if (!blocking) return { block: false, reason: null }; if (!OPERATIONAL_APPROVAL_TYPES.has(blocking.type as ApprovalType)) { return { block: false, reason: null }; diff --git a/src/main/agent-runtime/runtime-bridge.ts b/src/main/agent-runtime/runtime-bridge.ts index 6f10dade..14adf259 100644 --- a/src/main/agent-runtime/runtime-bridge.ts +++ b/src/main/agent-runtime/runtime-bridge.ts @@ -573,7 +573,7 @@ export class RuntimeBridge { // `?unreadOnly=true`, so agents posted status comments instead of // replies. The explicit read endpoint is the sole signal. const store = this.getOrCreateStore(payload.taskSessionId); - const inboxRecords = this.deps.db.listAgentInboxUnread(payload.companyId, payload.agentId); + const inboxRecords = this.deps.db.messages.listAgentInboxUnread(payload.companyId, payload.agentId); if (inboxRecords.length > 0) { this.deps.db.withTransaction(() => { for (const record of inboxRecords) { diff --git a/src/main/api-server/routes-agent-control.ts b/src/main/api-server/routes-agent-control.ts index 240cfe08..0a4e766e 100644 --- a/src/main/api-server/routes-agent-control.ts +++ b/src/main/api-server/routes-agent-control.ts @@ -31,7 +31,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) { }); const parsed = wakeSchema.safeParse(body); const reason = parsed.success ? parsed.data.reason : "peer_request"; - const alreadyActive = db.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId }); + const alreadyActive = db.runs.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId }); const runId = onWakeAgent(targetAgentId, token.companyId, reason); if (runId) { server.json(res, 200, { ok: true, runId, message: `Wake started for agent ${targetAgentId}` }); @@ -65,7 +65,7 @@ export function registerAgentControlRoutes(server: AgentApiServer) { server.json(res, 403, { error: "Current agent is not allowed to trigger heartbeat for this agent" }); return; } - const alreadyActive = db.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId }); + const alreadyActive = db.runs.hasActiveRun({ companyId: token.companyId, agentId: targetAgentId }); const runId = onWakeAgent(targetAgentId, token.companyId, "peer_request"); if (runId) { server.json(res, 200, { ok: true, runId, message: `Heartbeat triggered for agent ${targetAgentId}` }); diff --git a/src/main/api-server/routes-agents-standup.ts b/src/main/api-server/routes-agents-standup.ts index 915904ff..1e2f7e09 100644 --- a/src/main/api-server/routes-agents-standup.ts +++ b/src/main/api-server/routes-agents-standup.ts @@ -35,15 +35,15 @@ export function registerAgentStandupRoute(server: AgentApiServer): void { const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(); const recentComments = db.listRecentTaskComments([...allRelevantTaskIds], twoHoursAgo, 20); - const myPendingApprovals = db.listAgentPendingApprovals(token.companyId, token.agentId); - const myResolvedApprovals = db.listAgentResolvedApprovals(token.companyId, token.agentId, 5); + const myPendingApprovals = db.approvalsMod.listAgentPendingApprovals(token.companyId, token.agentId); + const myResolvedApprovals = db.approvalsMod.listAgentResolvedApprovals(token.companyId, token.agentId, 5); // Unread inbox lives in the standup briefing as the agent's // canonical view of pending communication. Pre-fix the agent had // to make a second API call to /messages?unreadOnly=true that the // model frequently skipped, so messages from peers and managers // sat dark while the agent posted heartbeat status comments. - const unreadInbox = db.listAgentInboxUnread(token.companyId, token.agentId); + const unreadInbox = db.messages.listAgentInboxUnread(token.companyId, token.agentId); const senderIds = new Set(unreadInbox.map((m) => m.fromAgentId)); const senderNames = senderIds.size > 0 ? new Map(db.agents.listAgentNamesByIds(token.companyId, Array.from(senderIds)).map((row) => [row.id, row.name])) diff --git a/src/main/api-server/routes-agents.ts b/src/main/api-server/routes-agents.ts index 95f4baf0..827d2672 100644 --- a/src/main/api-server/routes-agents.ts +++ b/src/main/api-server/routes-agents.ts @@ -29,7 +29,7 @@ export function registerAgentRoutes(server: AgentApiServer) { // and the standup module is registered separately in api-server/index.ts. server.addRoute("GET", "/api/agents/me/metrics", (_req, res, _params, token) => { - const companyMetrics = db.getCompanyMetrics(token.companyId, 30); + const companyMetrics = db.company.getCompanyMetrics(token.companyId, 30); const agentMetric = companyMetrics.agentMetrics.find(m => m.agentId === token.agentId); if (!agentMetric) { server.json(res, 404, { error: "Metrics not found" }); @@ -45,7 +45,7 @@ export function registerAgentRoutes(server: AgentApiServer) { server.json(res, 404, { error: "Agent not found" }); return; } - const companyMetrics = db.getCompanyMetrics(token.companyId, 30); + const companyMetrics = db.company.getCompanyMetrics(token.companyId, 30); const agentMetric = companyMetrics.agentMetrics.find((metric) => metric.agentId === agentId); if (!agentMetric) { server.json(res, 404, { error: "Metrics not found" }); @@ -190,7 +190,7 @@ export function registerAgentRoutes(server: AgentApiServer) { return; } // Also check pending hire approvals with the same name to prevent concurrent duplicate requests - const pendingHires = db.listPendingHireApprovalPayloads(companyId); + const pendingHires = db.approvalsMod.listPendingHireApprovalPayloads(companyId); for (const pending of pendingHires) { try { const payload = pending.payloadJson ? JSON.parse(pending.payloadJson) as Record : {}; diff --git a/src/main/api-server/routes-approvals.ts b/src/main/api-server/routes-approvals.ts index 64af7c02..5ef1c056 100644 --- a/src/main/api-server/routes-approvals.ts +++ b/src/main/api-server/routes-approvals.ts @@ -48,7 +48,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { // Reject the request at the API boundary so the model cannot // circumvent the ordering by resubmitting. if (input.type === "approve_ceo_strategy") { - const companyHireApprovals = db.listCompanyApprovalsByType(companyId, "hire_agent"); + const companyHireApprovals = db.approvalsMod.listCompanyApprovalsByType(companyId, "hire_agent"); if (companyHireApprovals.length === 0) { server.json(res, 409, { error: "approve_ceo_strategy requires at least one hire_agent approval to exist first. Submit the intended hires, then file the strategy.", @@ -56,7 +56,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { }); return; } - const existingStrategy = db.listCompanyApprovalsByType(companyId, "approve_ceo_strategy") + const existingStrategy = db.approvalsMod.listCompanyApprovalsByType(companyId, "approve_ceo_strategy") .find((a) => a.state === "pending" || a.state === "approved"); if (existingStrategy) { server.json(res, 409, { @@ -70,7 +70,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { let id: string; try { - id = db.requestApproval({ + id = db.approvalsMod.requestApproval({ companyId, type: input.type, relatedTaskId: input.relatedTaskId ?? null, @@ -139,7 +139,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { return; } const statuses = parsedQuery.data.status?.split(",").filter(Boolean) ?? null; - const approvals = db.listApprovalsForApi(companyId, { + const approvals = db.approvalsMod.listApprovalsForApi(companyId, { requestedByAgentId: parsedQuery.data.requestedByAgentId, relatedTaskId: parsedQuery.data.relatedTaskId, statuses, @@ -148,7 +148,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { }); server.addRoute("GET", "/api/approvals/:approvalId", (_req, res, params, token) => { - const approval = db.findApprovalById(requireParam(params, "approvalId")); + const approval = db.approvalsMod.findApprovalById(requireParam(params, "approvalId")); if (!approval || approval.companyId !== token.companyId) { server.json(res, 404, { error: "Approval not found" }); return; @@ -162,21 +162,21 @@ export function registerApprovalRoutes(server: AgentApiServer) { server.addRoute("GET", "/api/approvals/:approvalId/comments", (_req, res, params, token) => { const approvalId = requireParam(params, "approvalId"); - const approval = db.findApprovalById(approvalId); + const approval = db.approvalsMod.findApprovalById(approvalId); if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; } if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; } - const comments = db.listApprovalComments(approvalId, approval.companyId); + const comments = db.approvalsMod.listApprovalComments(approvalId, approval.companyId); server.json(res, 200, comments); }); server.addRoute("POST", "/api/approvals/:approvalId/comments", (_req, res, params, token, body) => { - const approval = db.findApprovalById(requireParam(params, "approvalId")); + const approval = db.approvalsMod.findApprovalById(requireParam(params, "approvalId")); if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; } if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; } const data = body as Record; const commentBody = typeof data.body === "string" ? data.body.trim() : ""; if (!commentBody) { server.json(res, 400, { error: "Comment body is required" }); return; } - const commentId = db.addApprovalComment({ + const commentId = db.approvalsMod.addApprovalComment({ companyId: approval.companyId, approvalId: approval.id, authorAgentId: token.agentId ?? null, @@ -194,7 +194,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { }); server.addRoute("POST", "/api/approvals/:approvalId/resubmit", (_req, res, params, token) => { - const approval = db.findApprovalById(requireParam(params, "approvalId")); + const approval = db.approvalsMod.findApprovalById(requireParam(params, "approvalId")); if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; } if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; } if (approval.state !== "revision_requested") { @@ -205,23 +205,23 @@ export function registerApprovalRoutes(server: AgentApiServer) { server.json(res, 403, { error: "Only the requesting agent can resubmit this approval" }); return; } - db.resubmitApproval(approval.id, approval.companyId); + db.approvalsMod.resubmitApproval(approval.id, approval.companyId); onDomainChanged(); server.json(res, 200, { resubmitted: true }); }); server.addRoute("GET", "/api/approvals/:approvalId/tasks", (_req, res, params, token) => { const approvalId = requireParam(params, "approvalId"); - const approval = db.findApprovalById(approvalId); + const approval = db.approvalsMod.findApprovalById(approvalId); if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; } if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; } - const taskIds = db.listTasksForApproval(approvalId); + const taskIds = db.approvalsMod.listTasksForApproval(approvalId); server.json(res, 200, taskIds); }); server.addRoute("POST", "/api/approvals/:approvalId/tasks", (_req, res, params, token, body) => { const approvalId = requireParam(params, "approvalId"); - const approval = db.findApprovalById(approvalId); + const approval = db.approvalsMod.findApprovalById(approvalId); if (!approval) { server.json(res, 404, { error: "Approval not found" }); return; } if (approval.companyId !== token.companyId) { server.json(res, 403, { error: "Company mismatch" }); return; } const data = body as Record; @@ -232,7 +232,7 @@ export function registerApprovalRoutes(server: AgentApiServer) { server.json(res, 400, { error: `Task ${taskId} does not belong to this company` }); return; } } - db.linkManyTasksToApproval(approvalId, taskIds, token.companyId, token.agentId ?? null); + db.approvalsMod.linkManyTasksToApproval(approvalId, taskIds, token.companyId, token.agentId ?? null); onDomainChanged(); server.json(res, 200, { linked: taskIds.length }); }); diff --git a/src/main/api-server/routes-messages.ts b/src/main/api-server/routes-messages.ts index 75e63b0d..65485fcd 100644 --- a/src/main/api-server/routes-messages.ts +++ b/src/main/api-server/routes-messages.ts @@ -142,7 +142,7 @@ export function registerMessageRoutes(server: AgentApiServer) { return; } - const messages = db.listAgentMessages(companyId, { + const messages = db.messages.listAgentMessages(companyId, { agentId: token.agentId, channel: channelParam ?? undefined, channelTargetId: channelTargetId && channelTargetId.length > 0 ? channelTargetId : undefined, @@ -158,12 +158,12 @@ export function registerMessageRoutes(server: AgentApiServer) { server.json(res, 403, { error: "Company mismatch" }); return; } - const message = db.getAgentMessage(requireParam(params, "messageId"), companyId); + const message = db.messages.getAgentMessage(requireParam(params, "messageId"), companyId); if (!message) { server.json(res, 404, { error: "Message not found" }); return; } - const visibleToAgent = db.listAgentMessages(companyId, { + const visibleToAgent = db.messages.listAgentMessages(companyId, { agentId: token.agentId, messageId: message.id, limit: 1, @@ -172,7 +172,7 @@ export function registerMessageRoutes(server: AgentApiServer) { server.json(res, 403, { error: "This message is not visible to the current agent" }); return; } - db.markMessageReadForReader(requireParam(params, "messageId"), companyId, token.agentId); + db.messages.markMessageReadForReader(requireParam(params, "messageId"), companyId, token.agentId); onDomainChanged(); server.json(res, 200, { ok: true }); }); diff --git a/src/main/api-server/routes-misc.ts b/src/main/api-server/routes-misc.ts index 5955f29c..69ec6627 100644 --- a/src/main/api-server/routes-misc.ts +++ b/src/main/api-server/routes-misc.ts @@ -42,7 +42,7 @@ export function registerMiscRoutes(server: AgentApiServer) { const postActions = ["post", "reply", "dm"]; if (account.requireApproval && postActions.includes(input.actionType)) { - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, type: "dangerous_command", relatedTaskId: null, @@ -142,7 +142,7 @@ export function registerMiscRoutes(server: AgentApiServer) { const contentPreview = parsed.data.content.slice(0, 120) + (parsed.data.content.length > 120 ? "..." : ""); - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, requestedByAgentId: token.agentId, type: "social_post", diff --git a/src/main/api-server/routes-runs.ts b/src/main/api-server/routes-runs.ts index bd0c6bbf..c13eb6e1 100644 --- a/src/main/api-server/routes-runs.ts +++ b/src/main/api-server/routes-runs.ts @@ -16,7 +16,7 @@ function parsePositiveInt(value: string | null, fallback: number) { } function resolveAuthorizedRun(server: AgentApiServer, token: TokenPayload, runId: string) { - const runState = server.db.getRunAuthState(runId); + const runState = server.db.runs.getRunAuthState(runId); if (!runState || runState.companyId !== token.companyId || runState.agentId !== token.agentId) { return null; } @@ -40,7 +40,7 @@ export function registerRunRoutes(server: AgentApiServer) { const url = new URL(req.url ?? "/", `http://127.0.0.1:${server.port}`); const offset = parsePositiveInt(url.searchParams.get("offset"), 0); const limit = Math.min(parsePositiveInt(url.searchParams.get("limit"), DEFAULT_EVENT_LIMIT), MAX_EVENT_LIMIT); - const events = server.db.listRunEvents(runId, token.companyId, { offset, limit }); + const events = server.db.runs.listRunEvents(runId, token.companyId, { offset, limit }); server.json(res, 200, { events, nextOffset: offset + events.length }); }); @@ -66,7 +66,7 @@ export function registerRunRoutes(server: AgentApiServer) { const flushPendingEvents = () => { while (true) { - const events = server.db.listRunEventsAfter(runId, token.companyId, cursor, SSE_BATCH_LIMIT); + const events = server.db.runs.listRunEventsAfter(runId, token.companyId, cursor, SSE_BATCH_LIMIT); if (events.length === 0) return; for (const event of events) { writeSse(res, "run-event", event); diff --git a/src/main/api-server/routes-tasks.ts b/src/main/api-server/routes-tasks.ts index 6762c70e..4be995b0 100644 --- a/src/main/api-server/routes-tasks.ts +++ b/src/main/api-server/routes-tasks.ts @@ -136,7 +136,7 @@ export function registerTaskRoutes(server: AgentApiServer) { }); const reviewerAgent = db.entityCrud.getAgent(token.agentId); const docTitles = docs.map((d) => d.title).join(", "); - db.requestApproval({ + db.approvalsMod.requestApproval({ companyId: task.companyId, relatedTaskId: task.id, requestedByAgentId: token.agentId, diff --git a/src/main/api-server/routes-work-graph.ts b/src/main/api-server/routes-work-graph.ts index f828e902..b20dcb67 100644 --- a/src/main/api-server/routes-work-graph.ts +++ b/src/main/api-server/routes-work-graph.ts @@ -256,7 +256,7 @@ export function registerWorkGraphRoutes(server: AgentApiServer) { server.json(res, 403, { error: "Company mismatch" }); return; } - const { agents, tasks, recentActivity } = db.getDashboardSnapshot(companyId); + const { agents, tasks, recentActivity } = db.company.getDashboardSnapshot(companyId); const tasksByStatus: Record = {}; for (const t of tasks) { diff --git a/src/main/api-server/server-core.ts b/src/main/api-server/server-core.ts index fd38005c..8571217a 100644 --- a/src/main/api-server/server-core.ts +++ b/src/main/api-server/server-core.ts @@ -217,7 +217,7 @@ export class AgentApiServer { if (typeof claimedRunId !== "string" || claimedRunId.trim() !== token.runId) { return { ok: false, status: 401, error: "Missing or mismatched X-Agent-Company-Run-Id header" }; } - const runState = this._db.getRunAuthState(token.runId); + const runState = this._db.runs.getRunAuthState(token.runId); if (!runState || runState.companyId !== token.companyId || runState.agentId !== token.agentId) { return { ok: false, status: 403, error: "Token references an unknown or mismatched run" }; } diff --git a/src/main/approval-policy.ts b/src/main/approval-policy.ts index e85a9b8b..94584cad 100644 --- a/src/main/approval-policy.ts +++ b/src/main/approval-policy.ts @@ -20,7 +20,7 @@ export function resolveApprovalDecision({ actor?: string; }) { const note = decisionNote ?? ""; - db.decideApproval({ + db.approvalsMod.decideApproval({ companyId, approvalId, state, diff --git a/src/main/automation/automation-actions.ts b/src/main/automation/automation-actions.ts index a2c9fabf..c9169641 100644 --- a/src/main/automation/automation-actions.ts +++ b/src/main/automation/automation-actions.ts @@ -208,7 +208,7 @@ export function executeAutomationAction( } case "create_approval": { const approvalType = (config.approvalType as string) ?? "document_review"; - db.requestApproval({ + db.approvalsMod.requestApproval({ companyId: ctx.companyId, relatedTaskId: ctx.taskId ?? null, requestedByAgentId: ctx.agentId ?? null, @@ -340,7 +340,7 @@ export function executeAutomationAction( (approval) => approval.companyId === ctx.companyId && approval.state === "pending", ); for (const approval of pendingApprovals.slice(0, 5)) { - db.decideApproval({ + db.approvalsMod.decideApproval({ companyId: ctx.companyId, approvalId: approval.id, state: "approved", diff --git a/src/main/automation/automation-run-completion.ts b/src/main/automation/automation-run-completion.ts index f487ab34..e9680a6e 100644 --- a/src/main/automation/automation-run-completion.ts +++ b/src/main/automation/automation-run-completion.ts @@ -181,7 +181,7 @@ function createDeliverableReviewApproval( ): string { const { db, logger, publishDomainChanged, notify } = deps; const docTitles = docs.map((d) => d.title).join(", "); - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, relatedTaskId: taskId, requestedByAgentId: agentId, @@ -232,9 +232,9 @@ function decideTerminalStatus( companyId: string, ): "in_review" | "done" { if (agent.reportsTo !== null) return "in_review"; - const mode = db.getCompanyExecutionMode(companyId); + const mode = db.company.getCompanyExecutionMode(companyId); if (mode !== "ai_ceo") return "in_review"; - const settings = db.getCompanyApprovalSettings(companyId); + const settings = db.company.getCompanyApprovalSettings(companyId); return settings?.reviewDeliverables ? "in_review" : "done"; } diff --git a/src/main/automation/automation-workflow.ts b/src/main/automation/automation-workflow.ts index 3dd71a28..8b6d6546 100644 --- a/src/main/automation/automation-workflow.ts +++ b/src/main/automation/automation-workflow.ts @@ -160,7 +160,7 @@ export async function runWorkflowPipeline( const { config, ctx } = buildWorkflowActionContext(companyId, step, actor); if (step.requiresApproval) { - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, requestedByAgentId: actor?.id ?? null, relatedTaskId: ctx.taskId ?? null, diff --git a/src/main/bootstrap/recover-interrupted-tasks.ts b/src/main/bootstrap/recover-interrupted-tasks.ts index cab1d714..bde89517 100644 --- a/src/main/bootstrap/recover-interrupted-tasks.ts +++ b/src/main/bootstrap/recover-interrupted-tasks.ts @@ -21,7 +21,7 @@ export function emitCrashRecoveryNotification(deps: RecoverInterruptedTasksDeps) const interruptedCount = deps.db.lastInterruptedCount; if (interruptedCount <= 0) return; deps.logger.warn(`[bootstrap] Detected ${interruptedCount} interrupted runs from previous session. Sending recovery notification.`); - const interruptedRuns = deps.db.getInterruptedRunsForRecovery(); + const interruptedRuns = deps.db.runs.getInterruptedRunsForRecovery(); if (interruptedRuns.length === 0) return; deps.emitEvent({ type: "recovery-needed", interruptedRuns }); deps.notify({ diff --git a/src/main/browser-action-service.ts b/src/main/browser-action-service.ts index 3e369f28..9dc03253 100644 --- a/src/main/browser-action-service.ts +++ b/src/main/browser-action-service.ts @@ -27,9 +27,9 @@ export function createBrowserActionService({ * missing. Isolates the "approval row disappeared" case so the caller does * not need to nest a try/catch around the state machine. */ - function getApprovalOrNull(approvalId: string): ReturnType | null { + function getApprovalOrNull(approvalId: string): ReturnType | null { try { - return db.getApprovalRecord(approvalId); + return db.approvalsMod.getApprovalRecord(approvalId); } catch (err) { const classified = classifyUnknownError(err, { kind: "recoverable", diff --git a/src/main/checkpoint-engine.ts b/src/main/checkpoint-engine.ts index db4e9f32..079a0c76 100644 --- a/src/main/checkpoint-engine.ts +++ b/src/main/checkpoint-engine.ts @@ -27,7 +27,7 @@ interface CheckpointDeps { } export function getCompanyExecutionMode(db: AppDatabase, companyId: string): ExecutionMode { - return db.getCompanyExecutionMode(companyId) as ExecutionMode; + return db.company.getCompanyExecutionMode(companyId) as ExecutionMode; } export function createCheckpointEngine(deps: CheckpointDeps) { @@ -60,7 +60,7 @@ export function createCheckpointEngine(deps: CheckpointDeps) { // the moment delegation starts. if (task.parentId) return null; - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, relatedTaskId: taskId, requestedByAgentId: agentId, @@ -107,7 +107,7 @@ export function createCheckpointEngine(deps: CheckpointDeps) { ? "strategy_review" : "draft_review"; - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, relatedTaskId: taskId, requestedByAgentId: authorAgentId, @@ -154,7 +154,7 @@ export function createCheckpointEngine(deps: CheckpointDeps) { } // Check for pending approvals related to this agent's tasks - return db.hasPendingReviewApprovalForAgent(companyId, agentId); + return db.approvalsMod.hasPendingReviewApprovalForAgent(companyId, agentId); } catch (err) { logger.error(`[checkpoint] shouldPauseHeartbeat failed: ${err instanceof Error ? err.message : String(err)}`); return false; diff --git a/src/main/database-base.ts b/src/main/database-base.ts index 950d04db..c9538118 100644 --- a/src/main/database-base.ts +++ b/src/main/database-base.ts @@ -250,19 +250,6 @@ export class AppDatabaseBase { listSnapshot(options: { companyId?: string | null } = {}): ProfileSnapshot { return this.snap.listSnapshot(options); } listRendererSnapshot(): ProfileSnapshot { return this.snap.listRendererSnapshot(); } - // ─── Company ─────────────────────────────────────────────────────────────── - - saveCompany(input: { id?: string | null; name: string; description: string; status: string; autoApproveHires?: boolean; reviewDeliverables?: boolean; executionMode?: string }) { return this.company.saveCompany(input); } - deleteCompany(id: string) { return this.company.deleteCompany(id); } - getCompanyStatus(companyId: string) { return this.company.getCompanyStatus(companyId); } - getCompanyBasic(companyId: string) { return this.company.getCompanyBasic(companyId); } - getCompanyExecutionMode(companyId: string) { return this.company.getCompanyExecutionMode(companyId); } - getCompanyApprovalSettings(companyId: string) { return this.company.getCompanyApprovalSettings(companyId); } - listActiveCompanyIds() { return this.company.listActiveCompanyIds(); } - getCompanyMetrics(companyId: string, days: number = 30) { return this.company.getCompanyMetrics(companyId, days); } - getStandupReport(companyId: string) { return this.company.getStandupReport(companyId); } - getDashboardSnapshot(companyId: string) { return this.company.getDashboardSnapshot(companyId); } - // ─── Connectors ──────────────────────────────────────────────────────────── saveConnector(input: { id: ConnectorId; model: string | null; envBindingText: string; notes: string }) { this.connectorsCrud.saveConnector(input); } @@ -270,49 +257,6 @@ export class AppDatabaseBase { getConnector(id: ConnectorId) { return this.connectorsCrud.getConnector(id); } findConnector(id: ConnectorId) { return this.connectorsCrud.findConnector(id); } - // ─── Runs ────────────────────────────────────────────────────────────────── - - getRun(id: string) { return this.runs.getRun(id); } - getRunAuthState(runId: string) { return this.runs.getRunAuthState(runId); } - createRun(input: { id?: string; companyId: string; taskId: string | null; agentId: string; workspaceId: string | null; connectorId: ConnectorId }) { return this.runs.createRun(input); } - appendRunLog(runId: string, stream: "stdout" | "stderr", chunk: string) { return this.runs.appendRunLog(runId, stream, chunk); } - readRunLog(runId: string) { return this.runs.readRunLog(runId); } - readRunLogChunk(runId: string, offset = 0, limit = 65_536) { return this.runs.readRunLogChunk(runId, offset, limit); } - markRunStatus(runId: string, status: RunStatus, message: string) { return this.runs.markRunStatus(runId, status, message); } - finishRun(input: { runId: string; status: RunStatus; summary: string | null; errorMessage: string | null; exitCode: number | null; signal: string | null; model: string | null; unattributedCost: boolean }) { return this.runs.finishRun(input); } - recordCostEntry(input: { runId: string; companyId: string; agentId: string; taskId: string | null; connectorId: string; amountUsd: number | null; unattributed: boolean }) { return this.runs.recordCostEntry(input); } - hasActiveRun(filter: { companyId: string; taskId?: string; agentId?: string }) { return this.runs.hasActiveRun(filter); } - listQueuedRuns() { return this.runs.listQueuedRuns(); } - getInterruptedRunsForRecovery() { return this.runs.getInterruptedRunsForRecovery(); } - appendRunEvent(input: { companyId: string; runId: string; agentId: string; eventType: string; stream?: string | null; level?: string | null; message?: string | null; payload?: Record | null }) { return this.runs.appendRunEvent(input); } - listRunEvents(runId: string, companyId: string, opts?: { offset?: number; limit?: number }) { return this.runs.listRunEvents(runId, companyId, opts); } - listRunEventsAfter(runId: string, companyId: string, afterSeq: number, limit: number) { return this.runs.listRunEventsAfter(runId, companyId, afterSeq, limit); } - updateRunActor(runId: string, actorType: string, actorId: string | null) { return this.runs.updateRunActor(runId, actorType, actorId); } - - // ─── Approvals ───────────────────────────────────────────────────────────── - - requestApproval(input: { companyId: string; relatedTaskId?: string | null; requestedByAgentId?: string | null; relatedAgentId?: string | null; type: string; payloadSummary: string; impactSummary: string; payloadJson?: string | null }) { return this.approvalsMod.requestApproval(input); } - decideApproval(input: { companyId?: string | null; approvalId: string; state: string; decisionNote: string }) { return this.approvalsMod.decideApproval(input); } - getApprovalRecord(id: string) { return this.approvalsMod.getApprovalRecord(id); } - findApprovalById(id: string) { return this.approvalsMod.findApprovalById(id); } - deleteApproval(id: string, companyId: string) { this.approvalsMod.deleteApproval(id, companyId); } - getBlockingApproval(companyId: string, agentId: string, taskId: string | null) { return this.approvalsMod.getBlockingApproval(companyId, agentId, taskId); } - resubmitApproval(approvalId: string, companyId: string) { this.approvalsMod.resubmitApproval(approvalId, companyId); } - addApprovalComment(input: { companyId: string; approvalId: string; authorAgentId?: string | null; authorUserId?: string | null; body: string }) { return this.approvalsMod.addApprovalComment(input); } - listApprovalComments(approvalId: string, companyId: string) { return this.approvalsMod.listApprovalComments(approvalId, companyId); } - linkTaskToApproval(taskId: string, approvalId: string, companyId: string, linkedByAgentId?: string | null) { this.approvalsMod.linkTaskToApproval(taskId, approvalId, companyId, linkedByAgentId); } - unlinkTaskFromApproval(taskId: string, approvalId: string) { this.approvalsMod.unlinkTaskFromApproval(taskId, approvalId); } - listApprovalsForTask(taskId: string) { return this.approvalsMod.listApprovalsForTask(taskId); } - listTasksForApproval(approvalId: string) { return this.approvalsMod.listTasksForApproval(approvalId); } - linkManyTasksToApproval(approvalId: string, taskIds: string[], companyId: string, linkedByAgentId?: string | null) { this.approvalsMod.linkManyTasksToApproval(approvalId, taskIds, companyId, linkedByAgentId); } - listAgentPendingApprovals(companyId: string, agentId: string) { return this.approvalsMod.listAgentPendingApprovals(companyId, agentId); } - listAgentResolvedApprovals(companyId: string, agentId: string, limit?: number) { return this.approvalsMod.listAgentResolvedApprovals(companyId, agentId, limit); } - listPendingHireApprovalPayloads(companyId: string) { return this.approvalsMod.listPendingHireApprovalPayloads(companyId); } - listApprovalsForApi(companyId: string, filters: { requestedByAgentId?: string; relatedTaskId?: string; statuses?: string[] | null }) { return this.approvalsMod.listApprovalsForApi(companyId, filters); } - findPendingApprovalForTask(companyId: string, taskId: string) { return this.approvalsMod.findPendingApprovalForTask(companyId, taskId); } - hasPendingReviewApprovalForAgent(companyId: string, agentId: string) { return this.approvalsMod.hasPendingReviewApprovalForAgent(companyId, agentId); } - listCompanyApprovalsByType(companyId: string, type: string) { return this.approvalsMod.listCompanyApprovalsByType(companyId, type); } - // ─── Workspaces ──────────────────────────────────────────────────────────── saveWorkspace(input: { id?: string | null; companyId: string; name: string; localPath: string; repoUrl: string; repoRef: string; projectId?: string | null; isPrimary: boolean }) { return this.workspacesMod.saveWorkspace(input); } diff --git a/src/main/database.ts b/src/main/database.ts index 709543d0..9f8444df 100644 --- a/src/main/database.ts +++ b/src/main/database.ts @@ -12,15 +12,6 @@ export class AppDatabase extends AppDatabaseBase { listComments(taskId: string) { return this.activityMod.listComments(taskId); } - // ─── Messages ────────────────────────────────────────────────────────────── - - sendAgentMessage(input: { companyId: string; fromAgentId: string; toAgentId?: string | null; channel?: string; channelTargetId?: string | null; subject: string; body: string; priority?: string; parentMessageId?: string | null; attachmentsJson?: string; senderKind?: "agent" | "human" | "system"; mentionedAgentIds?: readonly string[] }) { return this.messages.sendAgentMessage(input); } - getAgentMessage(messageId: string, companyId: string) { return this.messages.getAgentMessage(messageId, companyId); } - listAgentMessages(companyId: string, opts?: { agentId?: string; messageId?: string; channel?: string; channelTargetId?: string | null; unreadOnly?: boolean; limit?: number }) { return this.messages.listAgentMessages(companyId, opts); } - searchMessages(companyId: string, query: string, opts?: { channel?: string; channelTargetId?: string | null; limit?: number }) { return this.messages.searchMessages(companyId, query, opts); } - markMessageReadForReader(messageId: string, companyId: string, readerAgentId?: string | null) { return this.messages.markMessageReadForReader(messageId, companyId, readerAgentId); } - listAgentInboxUnread(companyId: string, agentId: string) { return this.messages.listAgentInboxUnread(companyId, agentId); } - // ─── Social & Browser Actions ────────────────────────────────────────────── saveSocialAccount(input: { id?: string | null; companyId: string; platform: string; accountName: string; displayName?: string; profileUrl?: string; credentialSecretId?: string | null; status?: string; requireApproval?: boolean; metadataJson?: string }) { return this.social.saveSocialAccount(input); } diff --git a/src/main/document-lifecycle.ts b/src/main/document-lifecycle.ts index 89a18a5c..f80e1da3 100644 --- a/src/main/document-lifecycle.ts +++ b/src/main/document-lifecycle.ts @@ -164,7 +164,7 @@ function deriveTaskIdFromRun( ): string | null { if (!runId) return null; try { - const run = db.getRun(runId); + const run = db.runs.getRun(runId); if (run.companyId !== companyId) return null; return run.taskId ?? null; } catch (error) { @@ -187,12 +187,12 @@ function maybeRaiseDeliverableReviewApproval( documentId: string, taskId: string | null, ): string | null { - const companySettings = deps.db.getCompanyApprovalSettings(input.companyId); + const companySettings = deps.db.company.getCompanyApprovalSettings(input.companyId); if (!companySettings?.reviewDeliverables) return null; - if (deps.db.getCompanyExecutionMode(input.companyId) === "ai_cofounder") return null; + if (deps.db.company.getCompanyExecutionMode(input.companyId) === "ai_cofounder") return null; if (deps.db.tasks.hasPendingDeliverableReviews(input.companyId)) return null; - const approvalId = deps.db.requestApproval({ + const approvalId = deps.db.approvalsMod.requestApproval({ companyId: input.companyId, relatedTaskId: taskId, requestedByAgentId: input.authorAgentId ?? "", diff --git a/src/main/execution-policy.ts b/src/main/execution-policy.ts index 812fa4c8..b42f5ed6 100644 --- a/src/main/execution-policy.ts +++ b/src/main/execution-policy.ts @@ -54,7 +54,7 @@ export function shouldAutoApprove( companyId: string, approvalType: string, ): boolean { - const rawMode = db.getCompanyExecutionMode(companyId); + const rawMode = db.company.getCompanyExecutionMode(companyId); assertExecutionMode(rawMode); const mode = rawMode; @@ -68,7 +68,7 @@ export function shouldAutoApprove( return false; } - const settings = db.getCompanyApprovalSettings(companyId); + const settings = db.company.getCompanyApprovalSettings(companyId); if (!settings?.autoApproveHires) return false; // When reviewDeliverables is ON, CEO strategy needs human review diff --git a/src/main/ipc-agent-coordination-handlers.ts b/src/main/ipc-agent-coordination-handlers.ts index 86b34b87..a9ab1a6c 100644 --- a/src/main/ipc-agent-coordination-handlers.ts +++ b/src/main/ipc-agent-coordination-handlers.ts @@ -56,7 +56,7 @@ export function registerAgentCoordinationHandlers({ const parsed = markMessageReadSchema.parse(payload); const companyError = ensureCompanyExists(parsed.companyId); if (companyError) return companyError; - const message = db.getAgentMessage(parsed.messageId, parsed.companyId); + const message = db.messages.getAgentMessage(parsed.messageId, parsed.companyId); if (!message) { return fail("MESSAGE_NOT_FOUND", "Message not found in the current company."); } @@ -64,7 +64,7 @@ export function registerAgentCoordinationHandlers({ return fail("INVALID_COMPANY_REFERENCE", "The selected message reader does not belong to the current company."); } if (parsed.readerAgentId) { - const visibleToReader = db + const visibleToReader = db.messages .listAgentMessages(parsed.companyId, { agentId: parsed.readerAgentId, messageId: parsed.messageId, @@ -75,7 +75,7 @@ export function registerAgentCoordinationHandlers({ return fail("MESSAGE_NOT_VISIBLE", "This message is not visible to the selected reader."); } } - db.markMessageReadForReader(parsed.messageId, parsed.companyId, parsed.readerAgentId ?? null); + db.messages.markMessageReadForReader(parsed.messageId, parsed.companyId, parsed.readerAgentId ?? null); publishDomainChanged(); return ok(true); }); @@ -84,7 +84,7 @@ export function registerAgentCoordinationHandlers({ const parsed = searchMessagesSchema.parse(payload); const companyError = ensureCompanyExists(parsed.companyId); if (companyError) return companyError; - return ok(db.searchMessages(parsed.companyId, parsed.query, { + return ok(db.messages.searchMessages(parsed.companyId, parsed.query, { channel: parsed.channel, channelTargetId: parsed.channelTargetId, limit: parsed.limit, diff --git a/src/main/ipc-core-admin-handlers.ts b/src/main/ipc-core-admin-handlers.ts index 0efec5ef..ddb077e1 100644 --- a/src/main/ipc-core-admin-handlers.ts +++ b/src/main/ipc-core-admin-handlers.ts @@ -46,11 +46,11 @@ export function registerCoreAdminHandlers({ >) { registerHandle(IPC_CHANNELS.saveCompany, async (_event, payload) => { const parsed = companyInputSchema.parse(payload); - const previousMode = parsed.id ? db.getCompanyExecutionMode(parsed.id) : parsed.executionMode; + const previousMode = parsed.id ? db.company.getCompanyExecutionMode(parsed.id) : parsed.executionMode; const previousApprovalSettings = parsed.id - ? db.getCompanyApprovalSettings(parsed.id) + ? db.company.getCompanyApprovalSettings(parsed.id) : { autoApproveHires: parsed.autoApproveHires, reviewDeliverables: parsed.reviewDeliverables }; - const id = db.saveCompany(parsed); + const id = db.company.saveCompany(parsed); reconcileExecutionModeChange({ db, companyId: id, @@ -159,7 +159,7 @@ export function registerCoreAdminHandlers({ if (!db.hasCompany(companyId)) { return fail("COMPANY_NOT_FOUND", "Company not found."); } - db.deleteCompany(companyId); + db.company.deleteCompany(companyId); publishDomainChanged(); return ok(true); }); diff --git a/src/main/ipc-core-agent-graph-handlers.ts b/src/main/ipc-core-agent-graph-handlers.ts index 9601c64e..c0ea14e6 100644 --- a/src/main/ipc-core-agent-graph-handlers.ts +++ b/src/main/ipc-core-agent-graph-handlers.ts @@ -298,14 +298,14 @@ export function registerCoreAgentGraphHandlers({ if (!db.belongsToCompany("approvals", parsed.id, parsed.companyId)) { return fail("APPROVAL_NOT_FOUND", "Approval not found in the current company."); } - const approval = db.getApprovalRecord(parsed.id); + const approval = db.approvalsMod.getApprovalRecord(parsed.id); if (approval.state === "pending" && approval.type === "hire_agent") { return fail( "APPROVAL_DELETE_BLOCKED", "Pending hire approvals cannot be deleted. Reject the hire request instead so the linked agent record stays consistent.", ); } - db.deleteApproval(parsed.id, parsed.companyId); + db.approvalsMod.deleteApproval(parsed.id, parsed.companyId); db.addActivity({ companyId: parsed.companyId, actor: "board", diff --git a/src/main/ipc-core-operations-handlers.ts b/src/main/ipc-core-operations-handlers.ts index 8761186f..d4286818 100644 --- a/src/main/ipc-core-operations-handlers.ts +++ b/src/main/ipc-core-operations-handlers.ts @@ -56,7 +56,7 @@ export function registerCoreOperationHandlers({ } let id: string; try { - id = db.requestApproval(parsed); + id = db.approvalsMod.requestApproval(parsed); } catch (error) { return fail("APPROVAL_INVALID", error instanceof Error ? error.message : "Approval could not be created."); } @@ -109,7 +109,7 @@ export function registerCoreOperationHandlers({ if (!db.belongsToCompany("approvals", parsed.approvalId, parsed.companyId)) { return fail("APPROVAL_NOT_FOUND", "Approval not found in the current company."); } - const approval = db.getApprovalRecord(parsed.approvalId); + const approval = db.approvalsMod.getApprovalRecord(parsed.approvalId); if (!approval || approval.companyId !== parsed.companyId) { return fail("APPROVAL_NOT_FOUND", "Approval not found in the current company."); } @@ -154,7 +154,7 @@ export function registerCoreOperationHandlers({ if (!db.belongsToCompany("runs", parsed.runId, parsed.companyId)) { return fail("RUN_NOT_FOUND", "Run not found in the current company."); } - return ok(db.readRunLog(parsed.runId)); + return ok(db.runs.readRunLog(parsed.runId)); }); registerHandle(IPC_CHANNELS.getRunLogChunk, (_event, payload) => { @@ -164,7 +164,7 @@ export function registerCoreOperationHandlers({ if (!db.belongsToCompany("runs", parsed.runId, parsed.companyId)) { return fail("RUN_NOT_FOUND", "Run not found in the current company."); } - return ok(db.readRunLogChunk(parsed.runId, parsed.offset, parsed.limit)); + return ok(db.runs.readRunLogChunk(parsed.runId, parsed.offset, parsed.limit)); }); registerHandle(IPC_CHANNELS.addComment, async (_event, payload) => { diff --git a/src/main/ipc-core-read-handlers.ts b/src/main/ipc-core-read-handlers.ts index f2ba01fb..c7d4a29a 100644 --- a/src/main/ipc-core-read-handlers.ts +++ b/src/main/ipc-core-read-handlers.ts @@ -149,14 +149,14 @@ export function registerCoreReadHandlers({ const input = metricsQuerySchema.parse(payload); const err = ensureCompanyExists(input.companyId); if (err) return err; - return ok(db.getCompanyMetrics(input.companyId, input.days)); + return ok(db.company.getCompanyMetrics(input.companyId, input.days)); }); registerHandle(IPC_CHANNELS.getStandupReport, (_event, payload) => { const companyId = z.string().uuid().parse(payload); const err = ensureCompanyExists(companyId); if (err) return err; - return ok(db.getStandupReport(companyId)); + return ok(db.company.getStandupReport(companyId)); }); // --- Entity getters for granular IPC updates --- @@ -194,7 +194,7 @@ export function registerCoreReadHandlers({ const companyError = ensureCompanyExists(parsed.companyId); if (companyError) return companyError; try { - const run = db.getRun(parsed.id); + const run = db.runs.getRun(parsed.id); if (run.companyId !== parsed.companyId) return fail("RUN_NOT_FOUND", "Run not found in current company."); return ok(run); } catch (err) { @@ -208,7 +208,7 @@ export function registerCoreReadHandlers({ const companyError = ensureCompanyExists(parsed.companyId); if (companyError) return companyError; try { - const approval = db.getApprovalRecord(parsed.id); + const approval = db.approvalsMod.getApprovalRecord(parsed.id); if (approval.companyId !== parsed.companyId) return fail("APPROVAL_NOT_FOUND", "Approval not found in current company."); return ok(approval); } catch (err) { diff --git a/src/main/messaging/dispatch.ts b/src/main/messaging/dispatch.ts index 9df282b8..ef24ae31 100644 --- a/src/main/messaging/dispatch.ts +++ b/src/main/messaging/dispatch.ts @@ -184,7 +184,7 @@ export function validateAgentMessageInput( } if (input.parentMessageId) { - const parentMessage = db.getAgentMessage(input.parentMessageId, input.companyId); + const parentMessage = db.messages.getAgentMessage(input.parentMessageId, input.companyId); if (!parentMessage) { return { code: "PARENT_MESSAGE_NOT_FOUND", @@ -317,8 +317,8 @@ export function dispatchAgentMessage( const persistedMessage = normalized.channel === "direct" ? { ...normalized, senderKind, mentionedAgentIds } : { ...normalized, toAgentId: null, senderKind, mentionedAgentIds }; - const id = deps.db.sendAgentMessage(persistedMessage); - const message = deps.db.getAgentMessage(id, normalized.companyId); + const id = deps.db.messages.sendAgentMessage(persistedMessage); + const message = deps.db.messages.getAgentMessage(id, normalized.companyId); if (message && deps.emitEvent) { deps.emitEvent({ type: "new-message", message }); } diff --git a/src/main/onboarding-service.ts b/src/main/onboarding-service.ts index eb44048b..6c49029f 100644 --- a/src/main/onboarding-service.ts +++ b/src/main/onboarding-service.ts @@ -220,7 +220,7 @@ export function createOnboardingService({ const connectors = db.listSnapshot({ companyId: null }).connectors; const selectedConnectorId = resolveOnboardingConnector(connectors, input.connectorId); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: input.companyName.trim(), description: input.companyDescription.trim(), status: "active", diff --git a/src/main/orchestration/heartbeat.ts b/src/main/orchestration/heartbeat.ts index 1ddd9e61..aea1ca7a 100644 --- a/src/main/orchestration/heartbeat.ts +++ b/src/main/orchestration/heartbeat.ts @@ -66,7 +66,7 @@ export function createHeartbeat( const isMessageWake = trigger === "message"; const isCommunicationWake = isMessageWake || trigger === "peer_request"; if (!hasWorkerReady()) return SKIPPED("worker_not_ready"); - const companyStatus = db.getCompanyStatus(companyId); + const companyStatus = db.company.getCompanyStatus(companyId); if (companyStatus !== "active") return SKIPPED("company_inactive"); const agent = db.entityCrud.getAgent(agentId); if (agent.companyId !== companyId) { @@ -131,8 +131,8 @@ export function createHeartbeat( } if (db.agents.isAgentPendingApproval(agentId)) return SKIPPED("pending_approval"); - const companyMode = db.getCompanyExecutionMode(companyId); - const approvalSettings = db.getCompanyApprovalSettings(companyId); + const companyMode = db.company.getCompanyExecutionMode(companyId); + const approvalSettings = db.company.getCompanyApprovalSettings(companyId); const shouldEnforceHumanReview = companyMode === "ai_cofounder" || approvalSettings?.reviewDeliverables === true; @@ -207,7 +207,7 @@ export function createHeartbeat( `[heartbeat] Workspace resolution for ${agent.name}: task.workspaceId=${task?.workspaceId ?? "null"}, agent.workspaceId=${agent.workspaceId ?? "null"}, projectId=${task?.projectId ?? "null"}, source=${workspaceResolution.source}, mode=${workspaceResolution.lockMode}, resolved=${workspace?.name ?? "NONE"}, localPath=${workspace?.localPath ?? "NONE"}`, ); - const run = db.createRun({ + const run = db.runs.createRun({ id: runId, companyId, taskId: task?.id ?? null, @@ -216,7 +216,7 @@ export function createHeartbeat( connectorId: connector.id, }); - const companyBasic = db.getCompanyBasic(companyId); + const companyBasic = db.company.getCompanyBasic(companyId); dispatchRunToWorker({ runId: run.id, companyId, @@ -238,7 +238,7 @@ export function createHeartbeat( try { const actorType = trigger === "timer" || trigger === "bootstrap" ? "system" : "agent"; const actorId = trigger === "timer" || trigger === "bootstrap" ? null : trigger; - db.updateRunActor(run.id, actorType, actorId); + db.runs.updateRunActor(run.id, actorType, actorId); } catch (error) { logger.warn( `[heartbeat] updateRunActor failed for run ${run.id}: ${error instanceof Error ? error.message : String(error)}`, diff --git a/src/main/orchestration/index.ts b/src/main/orchestration/index.ts index 84159dd3..87620e91 100644 --- a/src/main/orchestration/index.ts +++ b/src/main/orchestration/index.ts @@ -8,7 +8,7 @@ export function createOrchestrationService(deps: OrchestrationDependencies) { const { db } = deps; function hasActiveRun(filter: { taskId?: string; agentId?: string; companyId: string }) { - return db.hasActiveRun(filter); + return db.runs.hasActiveRun(filter); } const runDispatch = createRunDispatch(deps); diff --git a/src/main/orchestration/initial-user-turn.ts b/src/main/orchestration/initial-user-turn.ts index e51f163c..9515697c 100644 --- a/src/main/orchestration/initial-user-turn.ts +++ b/src/main/orchestration/initial-user-turn.ts @@ -44,7 +44,7 @@ export function resolveInitialUserTurn( } if (trigger === "message" || trigger === "peer_request") { - const unread = deps.db.listAgentInboxUnread(companyId, agentId); + const unread = deps.db.messages.listAgentInboxUnread(companyId, agentId); if (unread.length > 0) { return buildCommunicationTurn(trigger, unread, deps.db); } diff --git a/src/main/orchestration/run-dispatch.ts b/src/main/orchestration/run-dispatch.ts index 41424fbe..0b8c3ef3 100644 --- a/src/main/orchestration/run-dispatch.ts +++ b/src/main/orchestration/run-dispatch.ts @@ -83,7 +83,7 @@ export function createRunDispatch(deps: OrchestrationDependencies) { params.workspace && !db.claimWorkspaceLock(params.workspace.id, params.runId) ) { - db.finishRun({ + db.runs.finishRun({ runId: params.runId, status: "cancelled", summary: null, diff --git a/src/main/orchestration/scheduler-heartbeat.ts b/src/main/orchestration/scheduler-heartbeat.ts index c89bdcc5..13e3c972 100644 --- a/src/main/orchestration/scheduler-heartbeat.ts +++ b/src/main/orchestration/scheduler-heartbeat.ts @@ -67,7 +67,7 @@ export function createHeartbeatScheduler( try { if (isQuitting() || !hasWorkerReady()) return; - const activeCompanies = db.listActiveCompanyIds(); + const activeCompanies = db.company.listActiveCompanyIds(); const now = Date.now(); for (const company of activeCompanies) { diff --git a/src/main/orchestration/scheduler-housekeeping.ts b/src/main/orchestration/scheduler-housekeeping.ts index 47000f99..3f360db0 100644 --- a/src/main/orchestration/scheduler-housekeeping.ts +++ b/src/main/orchestration/scheduler-housekeeping.ts @@ -27,7 +27,7 @@ export function createHousekeepingScheduler( try { if (isQuitting() || !hasWorkerReady()) return; - const activeCompanies = db.listActiveCompanyIds(); + const activeCompanies = db.company.listActiveCompanyIds(); for (const company of activeCompanies) { try { @@ -52,7 +52,7 @@ export function createHousekeepingScheduler( dispatchAgentMessage, resolveApprovalDecision, notify, - getCompanyExecutionMode: (cId: string) => db.getCompanyExecutionMode(cId), + getCompanyExecutionMode: (cId: string) => db.company.getCompanyExecutionMode(cId), handleTaskStatusChange: (taskId: string, cId: string, previousStatus: string, newStatus: string) => { deps.dispatchAutomation("task_status_changed", { companyId: cId, taskId, previousStatus, newStatus }); publishDomainChanged(); diff --git a/src/main/orchestration/scheduler-idle-automation.ts b/src/main/orchestration/scheduler-idle-automation.ts index 92b2af43..35edd6b6 100644 --- a/src/main/orchestration/scheduler-idle-automation.ts +++ b/src/main/orchestration/scheduler-idle-automation.ts @@ -12,7 +12,7 @@ export function createIdleAutomationScheduler(deps: OrchestrationDependencies) { try { if (isQuitting() || !hasWorkerReady()) return; - const activeCompanies = db.listActiveCompanyIds(); + const activeCompanies = db.company.listActiveCompanyIds(); const now = Date.now(); for (const company of activeCompanies) { diff --git a/src/main/orchestration/task-runner.ts b/src/main/orchestration/task-runner.ts index f99d3bf7..69aecce6 100644 --- a/src/main/orchestration/task-runner.ts +++ b/src/main/orchestration/task-runner.ts @@ -38,7 +38,7 @@ export function createTaskRunner( return fail("WORKER_UNAVAILABLE", "Orchestration worker is not ready."); } const task = db.entityCrud.getTask(taskId); - const companyStatus = db.getCompanyStatus(task.companyId); + const companyStatus = db.company.getCompanyStatus(task.companyId); if (companyStatus !== "active") { return fail("COMPANY_NOT_ACTIVE", "Runs can only start while the company is active."); } @@ -78,7 +78,7 @@ export function createTaskRunner( if (db.agents.isAgentPendingApproval(agent.id)) { return fail("AGENT_PENDING_APPROVAL", "This agent is pending hire approval and cannot run tasks."); } - const blockingApproval = db.getBlockingApproval(task.companyId, agent.id, task.id); + const blockingApproval = db.approvalsMod.getBlockingApproval(task.companyId, agent.id, task.id); if (blockingApproval) { return fail( "APPROVAL_GATE_BLOCKED", @@ -99,7 +99,7 @@ export function createTaskRunner( return fail("WORKSPACE_COMPANY_MISMATCH", "The selected workspace does not belong to the task company."); } - const run = db.createRun({ + const run = db.runs.createRun({ id: runId, companyId: task.companyId, taskId: task.id, @@ -108,7 +108,7 @@ export function createTaskRunner( connectorId: connector.id, }); - const companyBasic = db.getCompanyBasic(task.companyId); + const companyBasic = db.company.getCompanyBasic(task.companyId); dispatchRunToWorker({ runId: run.id, companyId: task.companyId, @@ -163,7 +163,7 @@ export function createTaskRunner( const snapshot = db.listSnapshot(); const companiesById = new Map(snapshot.companies.map((company) => [company.id, company])); - for (const run of db.listQueuedRuns()) { + for (const run of db.runs.listQueuedRuns()) { const company = companiesById.get(run.companyId); if (!company || company.status !== "active") { continue; @@ -186,7 +186,7 @@ export function createTaskRunner( const eligibilityFailure = getRunEligibilityFailure(agent, connector, task?.projectId ?? null); if (eligibilityFailure) { if (eligibilityFailure === "CONNECTOR_MODEL_NOT_ALLOWED") { - db.finishRun({ + db.runs.finishRun({ runId: run.id, status: "failed", summary: "Queued run rejected during recovery because the agent model is disabled or invalid for its connector.", diff --git a/src/main/orchestration/turn-context.ts b/src/main/orchestration/turn-context.ts index af44cb10..35f3440c 100644 --- a/src/main/orchestration/turn-context.ts +++ b/src/main/orchestration/turn-context.ts @@ -288,7 +288,7 @@ export function buildRunPayload(params: RunDispatchParams, deps: TurnContextDeps task, companyName, locale: snapshot.locale, - executionMode: db.getCompanyExecutionMode(companyId) as ExecutionMode, + executionMode: db.company.getCompanyExecutionMode(companyId) as ExecutionMode, goals: snapshot.goals.filter((goal) => goal.companyId === companyId), projects: snapshot.projects.filter((project) => project.companyId === companyId), directReports: db.agents.getDirectReports(agent.id, companyId), @@ -354,7 +354,7 @@ export function buildRunPayload(params: RunDispatchParams, deps: TurnContextDeps systemPrompt, trigger, taskSessionId: taskSessionId ?? runId, - executionMode: db.getCompanyExecutionMode(companyId) as "ai_ceo" | "ai_cofounder", + executionMode: db.company.getCompanyExecutionMode(companyId) as "ai_ceo" | "ai_cofounder", initialUserTurn, }; } diff --git a/src/main/task-quality-gates.ts b/src/main/task-quality-gates.ts index 0f8ebf01..ada6b892 100644 --- a/src/main/task-quality-gates.ts +++ b/src/main/task-quality-gates.ts @@ -214,7 +214,7 @@ export function sweepStaleReviews( const chain = deps.db.agents.getChainOfCommand(reviewer.id); const escalationTarget = chain.length > 0 ? chain[0] : null; - const pendingApproval = deps.db.findPendingApprovalForTask(companyId, task.id); + const pendingApproval = deps.db.approvalsMod.findPendingApprovalForTask(companyId, task.id); // In ai_cofounder mode, ALL approvals require human decision — never auto-advance. if (isCofounderMode && pendingApproval) { diff --git a/src/main/thread-integration/index.ts b/src/main/thread-integration/index.ts index 83ed9816..ad811ed8 100644 --- a/src/main/thread-integration/index.ts +++ b/src/main/thread-integration/index.ts @@ -69,7 +69,7 @@ export function createThreadIntegration({ db, logger, emitEvent, publishDomainCh // In co-founder mode, set wait state when task enters review if (newStatus === "in_review") { - const mode = db.getCompanyExecutionMode(companyId) as ExecutionMode; + const mode = db.company.getCompanyExecutionMode(companyId) as ExecutionMode; if (mode === "ai_cofounder") { const reason = `@Board review needed: Task "${task.title}" is ready for your review.`; db.setThreadWaitState({ @@ -104,7 +104,7 @@ export function createThreadIntegration({ db, logger, emitEvent, publishDomainCh */ onApprovalCreated(approvalId: string, companyId: string, taskId: string | null, approvalType: string, summary: string): void { try { - const approval = db.getApprovalRecord(approvalId); + const approval = db.approvalsMod.getApprovalRecord(approvalId); const task = taskId ? db.entityCrud.getTask(taskId) : null; const thread = task ? ensureTaskThread(db, task.id, companyId, task.title) @@ -127,7 +127,7 @@ export function createThreadIntegration({ db, logger, emitEvent, publishDomainCh db.subscribe({ threadId: thread.id, subscriberId: "user", subscriberType: "user" }); // In co-founder mode, set wait state for user approval - const mode = db.getCompanyExecutionMode(companyId) as ExecutionMode; + const mode = db.company.getCompanyExecutionMode(companyId) as ExecutionMode; if (mode === "ai_cofounder") { const approvalReason = `@Board approval needed: ${approvalType}`; db.setThreadWaitState({ @@ -247,7 +247,7 @@ export function createThreadIntegration({ db, logger, emitEvent, publishDomainCh // In co-founder mode, successful runs create a user_reply wait state // so the heartbeat pauses until the human reviews the output if (status === "succeeded") { - const mode = db.getCompanyExecutionMode(companyId) as ExecutionMode; + const mode = db.company.getCompanyExecutionMode(companyId) as ExecutionMode; if (mode === "ai_cofounder") { const task = db.entityCrud.getTask(taskId); const completionReason = `@Board review needed: Agent completed work on "${task.title}" — awaiting your review.`; diff --git a/src/main/thread-integration/thread-helpers.ts b/src/main/thread-integration/thread-helpers.ts index 95ef9d15..4105bc4b 100644 --- a/src/main/thread-integration/thread-helpers.ts +++ b/src/main/thread-integration/thread-helpers.ts @@ -150,7 +150,7 @@ export function announceApprovalToBoard( ); if (!target) return; - const messageId = db.sendAgentMessage({ + const messageId = db.messages.sendAgentMessage({ companyId: approval.companyId, fromAgentId: approval.requestedByAgentId, channel: target.channel, @@ -160,7 +160,7 @@ export function announceApprovalToBoard( priority: "urgent", senderKind: "agent", }); - const message = db.getAgentMessage(messageId, approval.companyId); + const message = db.messages.getAgentMessage(messageId, approval.companyId); if (message) { deps.emitEvent({ type: "new-message", message }); } diff --git a/src/main/worker-service.ts b/src/main/worker-service.ts index 2dd2e3cb..089c5580 100644 --- a/src/main/worker-service.ts +++ b/src/main/worker-service.ts @@ -183,7 +183,7 @@ export function createWorkerService({ const snapshot = db.listSnapshot(); for (const run of snapshot.runs) { if (run.status === "running" || run.status === "queued") { - db.finishRun({ + db.runs.finishRun({ runId: run.id, status: "interrupted", summary: "Application shut down.", diff --git a/src/main/worker/entry/crash-recovery.ts b/src/main/worker/entry/crash-recovery.ts index c8cdde4c..489909fd 100644 --- a/src/main/worker/entry/crash-recovery.ts +++ b/src/main/worker/entry/crash-recovery.ts @@ -33,7 +33,7 @@ export function handleWorkerExit( for (const run of snapshot.runs) { if (run.status === "running") { - db.finishRun({ + db.runs.finishRun({ runId: run.id, status: "interrupted", summary: "Worker process crashed.", @@ -119,7 +119,7 @@ export function handleWorkerExit( }); } catch (error) { logger.warn(`[worker] Failed to re-enqueue run ${candidate.id}: ${error instanceof Error ? error.message : String(error)}`); - db.finishRun({ + db.runs.finishRun({ runId: candidate.id, status: "interrupted", summary: "Could not re-enqueue after worker restart.", diff --git a/src/main/worker/handlers/run-finished-helpers.ts b/src/main/worker/handlers/run-finished-helpers.ts index 53f09e7e..f0e4fec2 100644 --- a/src/main/worker/handlers/run-finished-helpers.ts +++ b/src/main/worker/handlers/run-finished-helpers.ts @@ -6,13 +6,13 @@ import type { workerMessageSchema } from "../entry/types"; import type { HandlerContext, HandlerDeps, WorkerMessageEvent } from "./handler-context"; type RunFinishedEvent = Extract; -type RunRecord = ReturnType; +type RunRecord = ReturnType; type TaskRecord = ReturnType; export interface RunFinishedContext { run: RunRecord; task: TaskRecord | null; - runOutcome: ReturnType; + runOutcome: ReturnType; } export function finalizeRun( @@ -25,7 +25,7 @@ export function finalizeRun( let run: RunRecord; try { - run = db.getRun(event.runId); + run = db.runs.getRun(event.runId); } catch (error) { logger.warn( `[finalizeRun] getRun(${event.runId}) failed; run may have been deleted: ${error instanceof Error ? error.message : String(error)}`, @@ -66,7 +66,7 @@ export function finalizeRun( } leaseRenewalMap.delete(event.runId); - const runOutcome = db.finishRun(event); + const runOutcome = db.runs.finishRun(event); if (run.workspaceId) { db.releaseWorkspaceLock(run.workspaceId, run.id); } @@ -350,7 +350,7 @@ function hasUnfinishedTeamBuilding( if (activeReports.length > 0) return false; const goalCount = db.countActiveGoalsForCompany(companyId); if (goalCount === 0) return false; - const pendingHires = db + const pendingHires = db.approvalsMod .listCompanyApprovalsByType(companyId, "hire_agent") .filter((a) => a.state === "pending"); return pendingHires.length === 0; diff --git a/src/main/worker/handlers/run-log-handler.ts b/src/main/worker/handlers/run-log-handler.ts index 9a166024..dbae9431 100644 --- a/src/main/worker/handlers/run-log-handler.ts +++ b/src/main/worker/handlers/run-log-handler.ts @@ -16,8 +16,8 @@ export async function handleRunLog( const filtered = filterRunLogChunk(event.stream, event.chunk); if (filtered === null) return; - await db.appendRunLog(event.runId, event.stream, filtered); - const runState = db.getRunAuthState(event.runId); + await db.runs.appendRunLog(event.runId, event.stream, filtered); + const runState = db.runs.getRunAuthState(event.runId); if (runState) { persistRunEvent(db, logger, { companyId: runState.companyId, @@ -36,7 +36,7 @@ export async function handleRunLog( const lastRenewal = leaseRenewalMap.get(event.runId) ?? 0; if (now - lastRenewal >= LEASE_RENEWAL_INTERVAL_MS) { try { - const run = db.getRun(event.runId); + const run = db.runs.getRun(event.runId); if (run.taskId) { db.tasks.renewTaskLease(run.taskId, run.id); } diff --git a/src/main/worker/handlers/run-status-handler.ts b/src/main/worker/handlers/run-status-handler.ts index 19720180..4ebf95d0 100644 --- a/src/main/worker/handlers/run-status-handler.ts +++ b/src/main/worker/handlers/run-status-handler.ts @@ -9,8 +9,8 @@ export function handleRunStatus( ): void { const { db, logger, emitEvent, onRunStarted } = deps; - const runState = db.getRunAuthState(event.runId); - db.markRunStatus(event.runId, event.status, event.message); + const runState = db.runs.getRunAuthState(event.runId); + db.runs.markRunStatus(event.runId, event.status, event.message); if (runState) { persistRunEvent(db, logger, { companyId: runState.companyId, @@ -30,7 +30,7 @@ export function handleRunStatus( // dispatchRunToWorker before enqueue. Only lease renewal and // run-started housekeeping run here. try { - const run = db.getRun(event.runId); + const run = db.runs.getRun(event.runId); if (run.taskId) { db.tasks.renewTaskLease(run.taskId, run.id); } diff --git a/src/main/worker/observability/run-event-recorder.ts b/src/main/worker/observability/run-event-recorder.ts index 0910f72b..d01bb53b 100644 --- a/src/main/worker/observability/run-event-recorder.ts +++ b/src/main/worker/observability/run-event-recorder.ts @@ -22,7 +22,7 @@ export function persistRunEvent( input: PersistInput, ) { try { - db.appendRunEvent(input); + db.runs.appendRunEvent(input); } catch (error) { logger.warn( `[run-events] Failed to append ${input.eventType} for ${input.runId}: ${ diff --git a/tests/integration/agent-model-switching.spec.ts b/tests/integration/agent-model-switching.spec.ts index d3ccf14d..395b4957 100644 --- a/tests/integration/agent-model-switching.spec.ts +++ b/tests/integration/agent-model-switching.spec.ts @@ -58,7 +58,7 @@ function createHarness(db: AppDatabase) { runDispatch.resolveWorkspace, runDispatch.getRunEligibilityFailure, runDispatch.dispatchRunToWorker, - (filter) => db.hasActiveRun(filter), + (filter) => db.runs.hasActiveRun(filter), ); return { enqueueWorkerRun, taskRunner }; @@ -78,7 +78,7 @@ describe("agent model switching", () => { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Model Switch Co", description: "Tests post-hire model switching", status: "active", @@ -126,7 +126,7 @@ describe("agent model switching", () => { throw new Error("Expected first run to queue successfully."); } - db.finishRun({ + db.runs.finishRun({ runId: firstRun.data, status: "succeeded", summary: "Done", diff --git a/tests/integration/api-recursive-org-execution.spec.ts b/tests/integration/api-recursive-org-execution.spec.ts index 1c05c0bf..eebf0e78 100644 --- a/tests/integration/api-recursive-org-execution.spec.ts +++ b/tests/integration/api-recursive-org-execution.spec.ts @@ -32,7 +32,7 @@ async function createHarness() { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Recursive Org Co", description: "Tests manager-driven recursive hires", status: "active", @@ -81,7 +81,7 @@ async function createHarness() { priority: "high", status: "in_progress", }); - const run = db.createRun({ companyId, taskId, agentId: ctoId, workspaceId, connectorId: "openai-codex" }); + const run = db.runs.createRun({ companyId, taskId, agentId: ctoId, workspaceId, connectorId: "openai-codex" }); const token = createAgentToken(ctoId, companyId, run.id); const server = createApiServer(db, () => {}, () => null); const port = await server.start(); @@ -130,12 +130,12 @@ describe("recursive org execution", () => { expect(pendingHire.status).toBe("pending_approval"); expect(pendingHire.reportsTo).toBe(harness.ctoId); - const approval = harness.db.getApprovalRecord(body.approvalId); + const approval = harness.db.approvalsMod.getApprovalRecord(body.approvalId); expect(approval.type).toBe("hire_agent"); expect(approval.requestedByAgentId).toBe(harness.ctoId); expect(approval.relatedAgentId).toBe(body.agentId); - harness.db.decideApproval({ + harness.db.approvalsMod.decideApproval({ approvalId: body.approvalId, state: "approved", decisionNote: "Approved by board", @@ -192,7 +192,7 @@ describe("recursive org execution", () => { priority: "high", status: "in_progress", }); - const hrRun = harness.db.createRun({ + const hrRun = harness.db.runs.createRun({ companyId: harness.companyId, taskId: hrTaskId, agentId: hrId, diff --git a/tests/integration/api-run-events.spec.ts b/tests/integration/api-run-events.spec.ts index 46b553c1..58a1594f 100644 --- a/tests/integration/api-run-events.spec.ts +++ b/tests/integration/api-run-events.spec.ts @@ -24,7 +24,7 @@ async function createHarness() { const db = new AppDatabase(profileDir); db.init(); - const companyId = db.saveCompany({ name: "Orbit Foundry", description: "API test", status: "active" }); + const companyId = db.company.saveCompany({ name: "Orbit Foundry", description: "API test", status: "active" }); const workspaceId = db.saveWorkspace({ companyId, name: "Primary", @@ -55,7 +55,7 @@ async function createHarness() { priority: "high", status: "todo", }); - const run = db.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "openai-codex" }); + const run = db.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "openai-codex" }); const token = createAgentToken(agentId, companyId, run.id); const server = createApiServer(db, () => {}, () => null); const port = await server.start(); @@ -95,7 +95,7 @@ describe("run event API", () => { it("returns persisted run events for the active run token", async () => { const harness = await createHarness(); try { - harness.db.appendRunEvent({ + harness.db.runs.appendRunEvent({ companyId: harness.companyId, runId: harness.runId, agentId: harness.agentId, @@ -141,7 +141,7 @@ describe("run event API", () => { expect(reader).toBeDefined(); setTimeout(() => { - harness.db.appendRunEvent({ + harness.db.runs.appendRunEvent({ companyId: harness.companyId, runId: harness.runId, agentId: harness.agentId, diff --git a/tests/integration/autonomous-chain/approval-decisions.spec.ts b/tests/integration/autonomous-chain/approval-decisions.spec.ts index 420a526c..56cd2c7c 100644 --- a/tests/integration/autonomous-chain/approval-decisions.spec.ts +++ b/tests/integration/autonomous-chain/approval-decisions.spec.ts @@ -14,7 +14,7 @@ describe("Step 4: Hire approval + decideApproval", () => { const ceoId = createAgent({ name: "CEO", role: "CEO" }); const hireId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "pending_approval" as "idle" }); - const approvalId = shared.db.requestApproval({ + const approvalId = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "hire_agent", @@ -23,7 +23,7 @@ describe("Step 4: Hire approval + decideApproval", () => { payloadJson: JSON.stringify({ agentId: hireId }), }); - shared.db.decideApproval({ + shared.db.approvalsMod.decideApproval({ approvalId, state: "approved", decisionNote: "Approved by board", @@ -37,7 +37,7 @@ describe("Step 4: Hire approval + decideApproval", () => { const ceoId = createAgent({ name: "CEO", role: "CEO" }); const hireId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "pending_approval" as "idle" }); - const approvalId = shared.db.requestApproval({ + const approvalId = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "hire_agent", @@ -46,7 +46,7 @@ describe("Step 4: Hire approval + decideApproval", () => { payloadJson: JSON.stringify({ agentId: hireId }), }); - shared.db.decideApproval({ + shared.db.approvalsMod.decideApproval({ approvalId, state: "rejected", decisionNote: "Not needed", @@ -59,7 +59,7 @@ describe("Step 4: Hire approval + decideApproval", () => { it("getApprovalRecord includes payloadJson", () => { const ceoId = createAgent({ name: "CEO", role: "CEO" }); const hireId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "pending_approval" as "idle" }); - const approvalId = shared.db.requestApproval({ + const approvalId = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "hire_agent", @@ -68,7 +68,7 @@ describe("Step 4: Hire approval + decideApproval", () => { payloadJson: JSON.stringify({ agentId: hireId, config: { connector: "openai-codex" } }), }); - const approval = shared.db.getApprovalRecord(approvalId); + const approval = shared.db.approvalsMod.getApprovalRecord(approvalId); expect(approval.payloadJson).toBeTruthy(); const payload = JSON.parse(approval.payloadJson!); expect(payload.agentId).toBe(hireId); diff --git a/tests/integration/autonomous-chain/automation-messages.spec.ts b/tests/integration/autonomous-chain/automation-messages.spec.ts index d7d9e929..d61cb926 100644 --- a/tests/integration/autonomous-chain/automation-messages.spec.ts +++ b/tests/integration/autonomous-chain/automation-messages.spec.ts @@ -104,7 +104,7 @@ describe("Agent Messages", () => { }); it("sends and retrieves direct messages", () => { - const msgId = shared.db.sendAgentMessage({ + const msgId = shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, toAgentId: agentBId, @@ -116,7 +116,7 @@ describe("Agent Messages", () => { expect(msgId).toBeTruthy(); - const messages = shared.db.listAgentMessages(shared.companyId); + const messages = shared.db.messages.listAgentMessages(shared.companyId); expect(messages).toHaveLength(1); expect(messages[0].subject).toBe("Need design review"); expect(messages[0].fromAgentId).toBe(agentAId); @@ -125,7 +125,7 @@ describe("Agent Messages", () => { }); it("marks messages as read", () => { - const msgId = shared.db.sendAgentMessage({ + const msgId = shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, toAgentId: agentBId, @@ -133,14 +133,14 @@ describe("Agent Messages", () => { body: "Hello", }); - shared.db.markMessageReadForReader(msgId, shared.companyId); - const messages = shared.db.listAgentMessages(shared.companyId); + shared.db.messages.markMessageReadForReader(msgId, shared.companyId); + const messages = shared.db.messages.listAgentMessages(shared.companyId); const updatedMessage = messages.find((message) => message.id === msgId); expect(updatedMessage?.readAt).toBeTruthy(); }); it("tracks read state per agent without marking the sender unread", () => { - const msgId = shared.db.sendAgentMessage({ + const msgId = shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, toAgentId: agentBId, @@ -148,22 +148,22 @@ describe("Agent Messages", () => { body: "Hello", }); - const senderView = shared.db.listAgentMessages(shared.companyId, { agentId: agentAId }); + const senderView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: agentAId }); expect(senderView).toHaveLength(1); expect(senderView[0].id).toBe(msgId); expect(senderView[0].readAt).toBeTruthy(); - const recipientViewBefore = shared.db.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true }); + const recipientViewBefore = shared.db.messages.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true }); expect(recipientViewBefore).toHaveLength(1); expect(recipientViewBefore[0].id).toBe(msgId); - shared.db.markMessageReadForReader(msgId, shared.companyId, agentBId); + shared.db.messages.markMessageReadForReader(msgId, shared.companyId, agentBId); - const recipientViewAfter = shared.db.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true }); + const recipientViewAfter = shared.db.messages.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true }); expect(recipientViewAfter).toHaveLength(0); const thirdAgentId = createAgent({ name: "Agent C" }); - const thirdView = shared.db.listAgentMessages(shared.companyId, { agentId: thirdAgentId }); + const thirdView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: thirdAgentId }); expect(thirdView).toHaveLength(0); }); @@ -188,7 +188,7 @@ describe("Agent Messages", () => { priority: "medium", }); - const deptMessageId = shared.db.sendAgentMessage({ + const deptMessageId = shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: engineeringLeadId, channel: "department", @@ -196,7 +196,7 @@ describe("Agent Messages", () => { subject: "Engineering update", body: "Only engineering should see this", }); - const projectMessageId = shared.db.sendAgentMessage({ + const projectMessageId = shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: engineeringLeadId, channel: "project", @@ -205,30 +205,30 @@ describe("Agent Messages", () => { body: "Only project members should see this", }); - const engineeringView = shared.db.listAgentMessages(shared.companyId, { agentId: engineeringLeadId }); + const engineeringView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: engineeringLeadId }); expect(engineeringView.some((message) => message.id === deptMessageId)).toBe(true); expect(engineeringView.some((message) => message.id === projectMessageId)).toBe(true); - const productView = shared.db.listAgentMessages(shared.companyId, { agentId: productLeadId }); + const productView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: productLeadId }); expect(productView.some((message) => message.id === deptMessageId)).toBe(false); expect(productView.some((message) => message.id === projectMessageId)).toBe(false); }); it("filters messages by channel", () => { - shared.db.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, subject: "Dept update", body: "All good", channel: "department", channelTargetId: "engineering" }); - shared.db.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, toAgentId: agentBId, subject: "DM", body: "Hey", channel: "direct" }); + shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, subject: "Dept update", body: "All good", channel: "department", channelTargetId: "engineering" }); + shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, toAgentId: agentBId, subject: "DM", body: "Hey", channel: "direct" }); - const deptMsgs = shared.db.listAgentMessages(shared.companyId, { channel: "department" }); + const deptMsgs = shared.db.messages.listAgentMessages(shared.companyId, { channel: "department" }); expect(deptMsgs).toHaveLength(1); expect(deptMsgs[0].subject).toBe("Dept update"); - const directMsgs = shared.db.listAgentMessages(shared.companyId, { channel: "direct" }); + const directMsgs = shared.db.messages.listAgentMessages(shared.companyId, { channel: "direct" }); expect(directMsgs).toHaveLength(1); expect(directMsgs[0].subject).toBe("DM"); }); it("appears in snapshot", () => { - shared.db.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, channel: "company", subject: "Snapshot test", body: "Hi" }); + shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, channel: "company", subject: "Snapshot test", body: "Hi" }); const snapshot = shared.db.listSnapshot(); expect(snapshot.agentMessages.length).toBeGreaterThanOrEqual(1); expect(snapshot.agentMessages[0].subject).toBe("Snapshot test"); diff --git a/tests/integration/autonomous-chain/crash-recovery.spec.ts b/tests/integration/autonomous-chain/crash-recovery.spec.ts index 4f6f69b1..185873af 100644 --- a/tests/integration/autonomous-chain/crash-recovery.spec.ts +++ b/tests/integration/autonomous-chain/crash-recovery.spec.ts @@ -23,7 +23,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => { status: "in_progress", }); - const run = shared.db.createRun({ + const run = shared.db.runs.createRun({ companyId: shared.companyId, taskId, agentId, @@ -31,7 +31,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => { connectorId: "openai-codex", }); - shared.db.markRunStatus(run.id, "running", "Started"); + shared.db.runs.markRunStatus(run.id, "running", "Started"); // Verify it's running let snapshot = shared.db.listSnapshot(); @@ -61,7 +61,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => { status: "in_progress", }); - const run = shared.db.createRun({ + const run = shared.db.runs.createRun({ companyId: shared.companyId, taskId, agentId, @@ -69,10 +69,10 @@ describe("Step 7: Worker crash recovery (database layer)", () => { connectorId: "openai-codex", }); - shared.db.markRunStatus(run.id, "running", "Started"); + shared.db.runs.markRunStatus(run.id, "running", "Started"); // Simulate crash recovery - mark as interrupted - shared.db.finishRun({ + shared.db.runs.finishRun({ runId: run.id, status: "interrupted", summary: "Worker process crashed.", diff --git a/tests/integration/autonomous-chain/e2e-flows.spec.ts b/tests/integration/autonomous-chain/e2e-flows.spec.ts index d6d31d89..61a62397 100644 --- a/tests/integration/autonomous-chain/e2e-flows.spec.ts +++ b/tests/integration/autonomous-chain/e2e-flows.spec.ts @@ -31,7 +31,7 @@ describe("E2E: Full autonomous CEO cold start flow", () => { const cmoId = createAgent({ name: "Aria", role: "CMO", reportsTo: ceoId, status: "pending_approval" as "idle" }); // 3. CEO submits org strategy approval - const orgApprovalId = shared.db.requestApproval({ + const orgApprovalId = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "approve_ceo_strategy", @@ -64,7 +64,7 @@ describe("E2E: Full autonomous CEO cold start flow", () => { expect(phase1Prompt).toContain("Awaiting Org Strategy Approval"); // 4. Board approves hires - const hireApprovalCTO = shared.db.requestApproval({ + const hireApprovalCTO = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "hire_agent", @@ -72,9 +72,9 @@ describe("E2E: Full autonomous CEO cold start flow", () => { impactSummary: "Test", payloadJson: JSON.stringify({ agentId: ctoId }), }); - shared.db.decideApproval({ approvalId: hireApprovalCTO, state: "approved", decisionNote: "Approved" }); + shared.db.approvalsMod.decideApproval({ approvalId: hireApprovalCTO, state: "approved", decisionNote: "Approved" }); - const hireApprovalCMO = shared.db.requestApproval({ + const hireApprovalCMO = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "hire_agent", @@ -82,14 +82,14 @@ describe("E2E: Full autonomous CEO cold start flow", () => { impactSummary: "Test", payloadJson: JSON.stringify({ agentId: cmoId }), }); - shared.db.decideApproval({ approvalId: hireApprovalCMO, state: "approved", decisionNote: "Approved" }); + shared.db.approvalsMod.decideApproval({ approvalId: hireApprovalCMO, state: "approved", decisionNote: "Approved" }); // Agents now idle expect(shared.db.entityCrud.getAgent(ctoId).status).toBe("idle"); expect(shared.db.entityCrud.getAgent(cmoId).status).toBe("idle"); // 5. Board approves org strategy - shared.db.decideApproval({ approvalId: orgApprovalId, state: "approved", decisionNote: "Go ahead" }); + shared.db.approvalsMod.decideApproval({ approvalId: orgApprovalId, state: "approved", decisionNote: "Go ahead" }); // 6. CEO now in Phase 2 const updatedCto = shared.db.entityCrud.getAgent(ctoId); @@ -287,7 +287,7 @@ describe("Review Fix: Rejected approval wakes agent", () => { it("decideApproval with rejected state still triggers wake (tested via DB)", () => { const ceoId = createAgent({ name: "CEO", role: "CEO" }); - const approvalId = shared.db.requestApproval({ + const approvalId = shared.db.approvalsMod.requestApproval({ companyId: shared.companyId, requestedByAgentId: ceoId, type: "approve_ceo_strategy", @@ -295,14 +295,14 @@ describe("Review Fix: Rejected approval wakes agent", () => { impactSummary: "test", }); - shared.db.decideApproval({ + shared.db.approvalsMod.decideApproval({ approvalId, state: "rejected", decisionNote: "Not ready", }); // Verify approval state - const approval = shared.db.getApprovalRecord(approvalId); + const approval = shared.db.approvalsMod.getApprovalRecord(approvalId); expect(approval.state).toBe("rejected"); // The IPC handler in index.ts now wakes on rejected too — // we verify the DB layer works; the wakeAgentIfPossible call is in index.ts diff --git a/tests/integration/autonomous-chain/run-failure.spec.ts b/tests/integration/autonomous-chain/run-failure.spec.ts index c0938be5..0bf7e067 100644 --- a/tests/integration/autonomous-chain/run-failure.spec.ts +++ b/tests/integration/autonomous-chain/run-failure.spec.ts @@ -22,7 +22,7 @@ describe("Step 6: Run failure escalation (database layer)", () => { status: "in_progress", }); - const run = shared.db.createRun({ + const run = shared.db.runs.createRun({ companyId: shared.companyId, taskId, agentId, @@ -30,9 +30,9 @@ describe("Step 6: Run failure escalation (database layer)", () => { connectorId: "openai-codex", }); - shared.db.markRunStatus(run.id, "running", "Started"); + shared.db.runs.markRunStatus(run.id, "running", "Started"); - const outcome = shared.db.finishRun({ + const outcome = shared.db.runs.finishRun({ runId: run.id, status: "failed", summary: null, diff --git a/tests/integration/autonomous-chain/shared-setup.ts b/tests/integration/autonomous-chain/shared-setup.ts index d00fae8e..6e4e1fcf 100644 --- a/tests/integration/autonomous-chain/shared-setup.ts +++ b/tests/integration/autonomous-chain/shared-setup.ts @@ -54,7 +54,7 @@ export function installSharedSetup(): SharedHandle { state.db = new AppDatabase(profileDir); state.db.init(); - state.companyId = state.db.saveCompany({ + state.companyId = state.db.company.saveCompany({ name: "Autonomous Test Corp", description: "Test company for autonomous chain", status: "active", diff --git a/tests/integration/connector-model-enforcement.spec.ts b/tests/integration/connector-model-enforcement.spec.ts index 57ae246a..690265a4 100644 --- a/tests/integration/connector-model-enforcement.spec.ts +++ b/tests/integration/connector-model-enforcement.spec.ts @@ -57,7 +57,7 @@ function createOrchestrationHarness(db: AppDatabase) { runDispatch.resolveWorkspace, runDispatch.getRunEligibilityFailure, runDispatch.dispatchRunToWorker, - (filter) => db.hasActiveRun(filter), + (filter) => db.runs.hasActiveRun(filter), ); return { deps, taskRunner }; @@ -77,7 +77,7 @@ describe("connector model enforcement", () => { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Runtime Enforcement Co", description: "Blocks runs when agent models are disabled", status: "active", @@ -141,7 +141,7 @@ describe("connector model enforcement", () => { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Recovered Run Co", description: "Rejects invalid queued runs during recovery", status: "active", @@ -177,7 +177,7 @@ describe("connector model enforcement", () => { status: "todo", }); - const run = db.createRun({ + const run = db.runs.createRun({ companyId, taskId, agentId, diff --git a/tests/integration/cross-subsystem.spec.ts b/tests/integration/cross-subsystem.spec.ts index 75f9b1dc..c0ccf974 100644 --- a/tests/integration/cross-subsystem.spec.ts +++ b/tests/integration/cross-subsystem.spec.ts @@ -64,7 +64,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult { notes: "Non-exempt connector for session rotation tests", }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Pipeline Test Corp", description: "Cross-subsystem pipeline integration tests", status: "active", @@ -187,7 +187,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { }); // 2. CAS checkout: create run and checkout task - const { id: runId } = db.createRun({ + const { id: runId } = db.runs.createRun({ companyId: s.companyId, taskId, agentId: s.agentId, @@ -207,9 +207,9 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { expect(budgetResult.blockedBy).toHaveLength(0); // 4. Execute run - db.markRunStatus(runId, "running", "Starting"); - db.recordCostEntry({ runId, companyId: s.companyId, agentId: s.agentId, taskId, connectorId: "gemini-cli", amountUsd: 0.05, unattributed: false }); - db.finishRun({ + db.runs.markRunStatus(runId, "running", "Starting"); + db.runs.recordCostEntry({ runId, companyId: s.companyId, agentId: s.agentId, taskId, connectorId: "gemini-cli", amountUsd: 0.05, unattributed: false }); + db.runs.finishRun({ runId, status: "succeeded", summary: "Login page built with form validation", @@ -229,7 +229,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { sessionService.accumulateTokenUsage(sessionId, 5000, 2000, runId); // 6. Verify final state - const run = db.getRun(runId); + const run = db.runs.getRun(runId); expect(run.status).toBe("succeeded"); const task = db.entityCrud.getTask(taskId); @@ -266,7 +266,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { }); // First agent checks out - const { id: runId1 } = db.createRun({ + const { id: runId1 } = db.runs.createRun({ companyId: s.companyId, taskId, agentId: s.agentId, @@ -289,7 +289,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { capabilities: "Backend development", budgetMonthlyUsd: 100, }); - const { id: runId2 } = db.createRun({ + const { id: runId2 } = db.runs.createRun({ companyId: s.companyId, taskId, agentId: agent2Id, @@ -322,7 +322,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { status: "todo", }); - const { id: runId } = db.createRun({ + const { id: runId } = db.runs.createRun({ companyId: s.companyId, taskId, agentId: s.agentId, @@ -331,9 +331,9 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { }); db.tasks.checkoutTask(taskId, runId); - db.markRunStatus(runId, "running", "Starting"); - db.recordCostEntry({ runId, companyId: s.companyId, agentId: s.agentId, taskId, connectorId: s.connectorId, amountUsd: 1.5, unattributed: false }); - db.finishRun({ + db.runs.markRunStatus(runId, "running", "Starting"); + db.runs.recordCostEntry({ runId, companyId: s.companyId, agentId: s.agentId, taskId, connectorId: s.connectorId, amountUsd: 1.5, unattributed: false }); + db.runs.finishRun({ runId, status: "succeeded", summary: "Done", @@ -382,7 +382,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { }); // Run 1: create run and accumulate tokens - const { id: runId1 } = db.createRun({ + const { id: runId1 } = db.runs.createRun({ companyId: s.companyId, taskId, agentId: s.agentId, @@ -392,7 +392,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { sessionService.accumulateTokenUsage(sessionId, 5000, 2000, runId1); // Run 2: create another run and accumulate more tokens - const { id: runId2 } = db.createRun({ + const { id: runId2 } = db.runs.createRun({ companyId: s.companyId, taskId, agentId: s.agentId, @@ -432,7 +432,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { status: "todo", }); - const { id: runId1 } = db.createRun({ + const { id: runId1 } = db.runs.createRun({ companyId: s.companyId, taskId: taskId1, agentId: s.agentId, @@ -440,9 +440,9 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { connectorId: s.connectorId, }); db.tasks.checkoutTask(taskId1, runId1); - db.markRunStatus(runId1, "running", "Starting"); - db.recordCostEntry({ runId: runId1, companyId: s.companyId, agentId: s.agentId, taskId: taskId1, connectorId: s.connectorId, amountUsd: 3.0, unattributed: false }); - db.finishRun({ + db.runs.markRunStatus(runId1, "running", "Starting"); + db.runs.recordCostEntry({ runId: runId1, companyId: s.companyId, agentId: s.agentId, taskId: taskId1, connectorId: s.connectorId, amountUsd: 3.0, unattributed: false }); + db.runs.finishRun({ runId: runId1, status: "succeeded", summary: "First task done", @@ -473,7 +473,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { status: "todo", }); - const { id: runId2 } = db.createRun({ + const { id: runId2 } = db.runs.createRun({ companyId: s.companyId, taskId: taskId2, agentId: s.agentId, @@ -481,9 +481,9 @@ describe("Cross-Subsystem Pipeline (D-04)", () => { connectorId: s.connectorId, }); db.tasks.checkoutTask(taskId2, runId2); - db.markRunStatus(runId2, "running", "Starting"); - db.recordCostEntry({ runId: runId2, companyId: s.companyId, agentId: s.agentId, taskId: taskId2, connectorId: s.connectorId, amountUsd: 3.0, unattributed: false }); - db.finishRun({ + db.runs.markRunStatus(runId2, "running", "Starting"); + db.runs.recordCostEntry({ runId: runId2, companyId: s.companyId, agentId: s.agentId, taskId: taskId2, connectorId: s.connectorId, amountUsd: 3.0, unattributed: false }); + db.runs.finishRun({ runId: runId2, status: "succeeded", summary: "Second task done", diff --git a/tests/integration/database.spec.ts b/tests/integration/database.spec.ts index ec45e4bf..06ac58c6 100644 --- a/tests/integration/database.spec.ts +++ b/tests/integration/database.spec.ts @@ -37,7 +37,7 @@ describe("AppDatabase", () => { const db = new AppDatabase(profileDir); db.init(); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Orbit Foundry", description: "Test company", status: "active", @@ -113,7 +113,7 @@ describe("AppDatabase", () => { OPENAI_API_KEY: "sk-test-123", }); - const run = db.createRun({ + const run = db.runs.createRun({ companyId, taskId, agentId, @@ -121,11 +121,11 @@ describe("AppDatabase", () => { connectorId: "openai-codex", }); - await db.appendRunLog(run.id, "stdout", "hello from run\n"); - expect(db.readRunLog(run.id)).toContain("hello from run"); + await db.runs.appendRunLog(run.id, "stdout", "hello from run\n"); + expect(db.runs.readRunLog(run.id)).toContain("hello from run"); - db.markRunStatus(run.id, "running", "Connector launched"); - db.finishRun({ + db.runs.markRunStatus(run.id, "running", "Connector launched"); + db.runs.finishRun({ runId: run.id, status: "succeeded", summary: "Completed successfully", @@ -143,7 +143,7 @@ describe("AppDatabase", () => { await db.exportBackup(backupDir); - db.saveCompany({ + db.company.saveCompany({ name: "Temporary company", description: "Should disappear after restore", status: "active", @@ -164,13 +164,13 @@ describe("AppDatabase", () => { const db = new AppDatabase(profileDir); db.init(); - const alphaCompanyId = db.saveCompany({ + const alphaCompanyId = db.company.saveCompany({ name: "Alpha", description: "Alpha company", status: "active", }); - const betaCompanyId = db.saveCompany({ + const betaCompanyId = db.company.saveCompany({ name: "Beta", description: "Beta company", status: "active", diff --git a/tests/integration/document-run-provenance.spec.ts b/tests/integration/document-run-provenance.spec.ts index 466c5784..7d04cc17 100644 --- a/tests/integration/document-run-provenance.spec.ts +++ b/tests/integration/document-run-provenance.spec.ts @@ -34,7 +34,7 @@ async function createHarness() { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Document Provenance Co", description: "Tests document revision provenance through run completion", status: "active", @@ -82,7 +82,7 @@ async function createHarness() { status: "draft", }); - const run = db.createRun({ + const run = db.runs.createRun({ companyId, taskId, agentId, @@ -284,7 +284,7 @@ describe("document run provenance", () => { it("creates deliverable review approvals that stay linked to the originating task", async () => { const harness = await createHarness(); try { - harness.db.saveCompany({ + harness.db.company.saveCompany({ id: harness.companyId, name: "Document Provenance Co", description: "Tests document review task linkage", diff --git a/tests/integration/process-recovery.spec.ts b/tests/integration/process-recovery.spec.ts index dddebf8f..e873bba7 100644 --- a/tests/integration/process-recovery.spec.ts +++ b/tests/integration/process-recovery.spec.ts @@ -62,7 +62,7 @@ function scaffold(db: AppDatabase): ScaffoldResult { }); // Company - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Recovery Test Corp", description: "Process recovery integration tests", status: "active", @@ -157,7 +157,7 @@ function createAndStartRun( status: "todo", }); - const { id: runId } = db.createRun({ + const { id: runId } = db.runs.createRun({ companyId: opts.companyId, taskId, agentId: opts.agentId, @@ -166,7 +166,7 @@ function createAndStartRun( }); db.tasks.checkoutTask(taskId, runId); - db.markRunStatus(runId, "running", "Starting execution"); + db.runs.markRunStatus(runId, "running", "Starting execution"); if (opts.claimWorkspace !== false) { db.claimWorkspaceLock(opts.workspaceId, runId); @@ -278,8 +278,8 @@ describe("Process Recovery -- Worker Crash Detection", () => { const interruptedCount = simulateWorkerCrash(db); expect(interruptedCount).toBe(2); - expect(db.getRun(run1.runId).status).toBe("interrupted"); - expect(db.getRun(run2.runId).status).toBe("interrupted"); + expect(db.runs.getRun(run1.runId).status).toBe("interrupted"); + expect(db.runs.getRun(run2.runId).status).toBe("interrupted"); }); it("releases task locks after crash", () => { @@ -378,7 +378,7 @@ describe("Process Recovery -- Worker Crash Detection", () => { priority: "medium", status: "todo", }); - const { id: newRunId } = db.createRun({ + const { id: newRunId } = db.runs.createRun({ companyId: s.companyId, taskId: taskId2, agentId: agent2Id, @@ -530,7 +530,7 @@ describe("Process Recovery -- Multiple Concurrent Runs", () => { expect(interruptedCount).toBe(3); for (const run of runs) { - expect(db.getRun(run.runId).status).toBe("interrupted"); + expect(db.runs.getRun(run.runId).status).toBe("interrupted"); } }); diff --git a/tests/integration/skill-aware-assignment.spec.ts b/tests/integration/skill-aware-assignment.spec.ts index bf74bd27..ddf1de20 100644 --- a/tests/integration/skill-aware-assignment.spec.ts +++ b/tests/integration/skill-aware-assignment.spec.ts @@ -32,7 +32,7 @@ describe("skill-aware capability registry", () => { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Skill Match Co", description: "Tests skill-aware assignment", status: "active", @@ -122,7 +122,7 @@ describe("skill-aware capability registry", () => { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Registry Co", description: "Tests capability registry prompt injection", status: "active", diff --git a/tests/integration/thread-wait-heartbeat.spec.ts b/tests/integration/thread-wait-heartbeat.spec.ts index 1777d16a..a9d73a56 100644 --- a/tests/integration/thread-wait-heartbeat.spec.ts +++ b/tests/integration/thread-wait-heartbeat.spec.ts @@ -36,7 +36,7 @@ function createScaffold(db: AppDatabase) { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Thread Wait Co", description: "Tests cofounder wait states and replies", status: "active", @@ -204,7 +204,7 @@ describe("thread wait + heartbeat integration", () => { throw new Error("Expected a task thread to exist for approval resolution testing."); } - const approvalId = db.requestApproval({ + const approvalId = db.approvalsMod.requestApproval({ companyId, relatedTaskId: taskId, requestedByAgentId: engineerId, @@ -238,7 +238,7 @@ describe("thread wait + heartbeat integration", () => { expect(waitStates).toHaveLength(1); expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(true); - db.decideApproval({ + db.approvalsMod.decideApproval({ approvalId, state: "approved", decisionNote: "Approved by board", diff --git a/tests/integration/work-products-lifecycle.spec.ts b/tests/integration/work-products-lifecycle.spec.ts index d841cbe4..d84c7980 100644 --- a/tests/integration/work-products-lifecycle.spec.ts +++ b/tests/integration/work-products-lifecycle.spec.ts @@ -53,7 +53,7 @@ async function createHarness(): Promise { lastError: null, }); - const companyId = db.saveCompany({ + const companyId = db.company.saveCompany({ name: "Work Products Co", description: "Tests archived visibility, bulk retirement, deliverable signal", status: "active", @@ -88,7 +88,7 @@ async function createHarness(): Promise { priority: "medium", status: "in_progress", }); - const run = db.createRun({ + const run = db.runs.createRun({ companyId, taskId, agentId, diff --git a/tests/unit/agent-budget-policy-sync.test.ts b/tests/unit/agent-budget-policy-sync.test.ts index 7cc5a949..518b88b5 100644 --- a/tests/unit/agent-budget-policy-sync.test.ts +++ b/tests/unit/agent-budget-policy-sync.test.ts @@ -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", diff --git a/tests/unit/agent-hire-routing.test.ts b/tests/unit/agent-hire-routing.test.ts index 92497da0..e1fb5759 100644 --- a/tests/unit/agent-hire-routing.test.ts +++ b/tests/unit/agent-hire-routing.test.ts @@ -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", diff --git a/tests/unit/agent-permissions.test.ts b/tests/unit/agent-permissions.test.ts index d508ec54..4da95caf 100644 --- a/tests/unit/agent-permissions.test.ts +++ b/tests/unit/agent-permissions.test.ts @@ -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", diff --git a/tests/unit/approval-hire-routing.test.ts b/tests/unit/approval-hire-routing.test.ts index 9a5ae78f..d54ab3aa 100644 --- a/tests/unit/approval-hire-routing.test.ts +++ b/tests/unit/approval-hire-routing.test.ts @@ -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", diff --git a/tests/unit/approval-review-feedback-writeback.test.ts b/tests/unit/approval-review-feedback-writeback.test.ts index b735f00e..dbf29cb9 100644 --- a/tests/unit/approval-review-feedback-writeback.test.ts +++ b/tests/unit/approval-review-feedback-writeback.test.ts @@ -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.", diff --git a/tests/unit/atomic-checkout.test.ts b/tests/unit/atomic-checkout.test.ts index 2430bea2..e62c3074 100644 --- a/tests/unit/atomic-checkout.test.ts +++ b/tests/unit/atomic-checkout.test.ts @@ -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); diff --git a/tests/unit/company-mode-switch.test.ts b/tests/unit/company-mode-switch.test.ts index 7f879e6a..c2af425f 100644 --- a/tests/unit/company-mode-switch.test.ts +++ b/tests/unit/company-mode-switch.test.ts @@ -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(); 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(); }); diff --git a/tests/unit/database.test.ts b/tests/unit/database.test.ts index e12bd70d..5ac8fa91 100644 --- a/tests/unit/database.test.ts +++ b/tests/unit/database.test.ts @@ -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); }); diff --git a/tests/unit/edge-case-budget.test.ts b/tests/unit/edge-case-budget.test.ts index a92e7ae7..df2f56b7 100644 --- a/tests/unit/edge-case-budget.test.ts +++ b/tests/unit/edge-case-budget.test.ts @@ -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", diff --git a/tests/unit/edge-case-concurrent.test.ts b/tests/unit/edge-case-concurrent.test.ts index 631e7cfb..26e0ca75 100644 --- a/tests/unit/edge-case-concurrent.test.ts +++ b/tests/unit/edge-case-concurrent.test.ts @@ -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, diff --git a/tests/unit/edge-case-session.test.ts b/tests/unit/edge-case-session.test.ts index 6ee66baa..603320c8 100644 --- a/tests/unit/edge-case-session.test.ts +++ b/tests/unit/edge-case-session.test.ts @@ -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", diff --git a/tests/unit/ipc-agent-graph-handlers.test.ts b/tests/unit/ipc-agent-graph-handlers.test.ts index b4183231..d056008d 100644 --- a/tests/unit/ipc-agent-graph-handlers.test.ts +++ b/tests/unit/ipc-agent-graph-handlers.test.ts @@ -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", diff --git a/tests/unit/knowledge-provenance.test.ts b/tests/unit/knowledge-provenance.test.ts index ebc484d5..bcab758a 100644 --- a/tests/unit/knowledge-provenance.test.ts +++ b/tests/unit/knowledge-provenance.test.ts @@ -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", diff --git a/tests/unit/message-dispatch.test.ts b/tests/unit/message-dispatch.test.ts index 5ab6bba9..ae9f6ae0 100644 --- a/tests/unit/message-dispatch.test.ts +++ b/tests/unit/message-dispatch.test.ts @@ -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(); diff --git a/tests/unit/message-search.test.ts b/tests/unit/message-search.test.ts index 8fd4c604..23353674 100644 --- a/tests/unit/message-search.test.ts +++ b/tests/unit/message-search.test.ts @@ -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++) { diff --git a/tests/unit/resolve-workspace.test.ts b/tests/unit/resolve-workspace.test.ts index 90b2a90e..aad855db 100644 --- a/tests/unit/resolve-workspace.test.ts +++ b/tests/unit/resolve-workspace.test.ts @@ -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", diff --git a/tests/unit/session-management.test.ts b/tests/unit/session-management.test.ts index e7d31005..4dd6ba98 100644 --- a/tests/unit/session-management.test.ts +++ b/tests/unit/session-management.test.ts @@ -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", diff --git a/tests/unit/task-quality-gates-sweep.test.ts b/tests/unit/task-quality-gates-sweep.test.ts index 27cb614c..b101d870 100644 --- a/tests/unit/task-quality-gates-sweep.test.ts +++ b/tests/unit/task-quality-gates-sweep.test.ts @@ -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; getChainOfCommand: ReturnType; }; - findPendingApprovalForTask: ReturnType; + approvalsMod: { + findPendingApprovalForTask: ReturnType; + }; }; 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).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); diff --git a/tests/unit/tasks-phase.test.ts b/tests/unit/tasks-phase.test.ts index 9be638f0..cb4f9a8a 100644 --- a/tests/unit/tasks-phase.test.ts +++ b/tests/unit/tasks-phase.test.ts @@ -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, diff --git a/tests/unit/wakeup-lifecycle.test.ts b/tests/unit/wakeup-lifecycle.test.ts index 39642294..9712b395 100644 --- a/tests/unit/wakeup-lifecycle.test.ts +++ b/tests/unit/wakeup-lifecycle.test.ts @@ -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",