refactor(db): group database domain modules

This commit is contained in:
ZacharyZhang-NY committed 2026-04-22 19:24:25 -04:00
1 parent e43a89096d
commit 6da0a58769
160 files changed
+2124 -1999

No files matched your search

@@ -58,7 +58,7 @@ function createHarness(db: AppDatabase) {
runDispatch.resolveWorkspace,
runDispatch.getRunEligibilityFailure,
runDispatch.dispatchRunToWorker,
(filter) => db.runs.hasActiveRun(filter),
(filter) => db.core.runs.hasActiveRun(filter),
);
return { enqueueWorkerRun, taskRunner };
@@ -70,7 +70,7 @@ describe("agent model switching", () => {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -78,12 +78,12 @@ describe("agent model switching", () => {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Model Switch Co",
description: "Tests post-hire model switching",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -91,7 +91,7 @@ describe("agent model switching", () => {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "Engineer",
role: "Engineer",
@@ -107,7 +107,7 @@ describe("agent model switching", () => {
const { enqueueWorkerRun, taskRunner } = createHarness(db);
const firstTaskId = db.tasks.saveTask({
const firstTaskId = db.core.tasks.saveTask({
companyId,
title: "Initial model task",
description: "Use the first model for this run.",
@@ -126,7 +126,7 @@ describe("agent model switching", () => {
throw new Error("Expected first run to queue successfully.");
}
db.runs.finishRun({
db.core.runs.finishRun({
runId: firstRun.data,
status: "succeeded",
summary: "Done",
@@ -137,7 +137,7 @@ describe("agent model switching", () => {
unattributedCost: true,
});
db.agents.saveAgent({
db.core.agents.saveAgent({
id: agentId,
companyId,
name: "Engineer",
@@ -152,7 +152,7 @@ describe("agent model switching", () => {
budgetMonthlyUsd: 200,
});
const secondTaskId = db.tasks.saveTask({
const secondTaskId = db.core.tasks.saveTask({
companyId,
title: "Updated model task",
description: "Use the new model for this run.",
@@ -25,7 +25,7 @@ async function createHarness() {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -33,12 +33,12 @@ async function createHarness() {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Recursive Org Co",
description: "Tests manager-driven recursive hires",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -46,7 +46,7 @@ async function createHarness() {
repoRef: "",
isPrimary: true,
});
const ceoId = db.agents.saveAgent({
const ceoId = db.core.agents.saveAgent({
companyId,
name: "CEO",
role: "CEO",
@@ -59,7 +59,7 @@ async function createHarness() {
capabilities: "Lead the company",
budgetMonthlyUsd: 250,
});
const ctoId = db.agents.saveAgent({
const ctoId = db.core.agents.saveAgent({
companyId,
name: "CTO",
role: "CTO",
@@ -73,7 +73,7 @@ async function createHarness() {
budgetMonthlyUsd: 220,
department: "engineering",
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Build the org",
description: "CTO should hire the first IC under engineering.",
@@ -82,7 +82,7 @@ async function createHarness() {
priority: "high",
status: "in_progress",
});
const run = db.runs.createRun({ companyId, taskId, agentId: ctoId, workspaceId, connectorId: "openai-codex" });
const run = db.core.runs.createRun({ companyId, taskId, agentId: ctoId, workspaceId, connectorId: "openai-codex" });
const token = createAgentToken(ctoId, companyId, run.id);
const server = createApiServer(db, createTestApiServerCallbacks());
const port = await server.start();
@@ -127,26 +127,26 @@ describe("recursive org execution", () => {
const body = await response.json() as { agentId: string; approvalId: string; autoApproved: boolean };
expect(body.autoApproved).toBe(false);
const pendingHire = harness.db.entityCrud.getAgent(body.agentId);
const pendingHire = harness.db.core.entity.getAgent(body.agentId);
expect(pendingHire.status).toBe("pending_approval");
expect(pendingHire.reportsTo).toBe(harness.ctoId);
const approval = harness.db.approvalsMod.getApprovalRecord(body.approvalId);
const approval = harness.db.core.approvals.getApprovalRecord(body.approvalId);
expect(approval.type).toBe("hire_agent");
expect(approval.requestedByAgentId).toBe(harness.ctoId);
expect(approval.relatedAgentId).toBe(body.agentId);
harness.db.approvalsMod.decideApproval({
harness.db.core.approvals.decideApproval({
approvalId: body.approvalId,
state: "approved",
decisionNote: "Approved by board",
});
const approvedHire = harness.db.entityCrud.getAgent(body.agentId);
const approvedHire = harness.db.core.entity.getAgent(body.agentId);
expect(approvedHire.status).toBe("idle");
expect(harness.db.agents.getDirectReports(harness.ctoId, harness.companyId).map((agent) => agent.id)).toContain(body.agentId);
expect(harness.db.agents.getDirectReports(harness.ceoId, harness.companyId).map((agent) => agent.id)).not.toContain(body.agentId);
expect(harness.db.agents.getChainOfCommand(body.agentId).map((agent) => agent.id)).toEqual([harness.ctoId, harness.ceoId]);
expect(harness.db.core.agents.getDirectReports(harness.ctoId, harness.companyId).map((agent) => agent.id)).toContain(body.agentId);
expect(harness.db.core.agents.getDirectReports(harness.ceoId, harness.companyId).map((agent) => agent.id)).not.toContain(body.agentId);
expect(harness.db.core.agents.getChainOfCommand(body.agentId).map((agent) => agent.id)).toEqual([harness.ctoId, harness.ceoId]);
const agentResponse = await fetch(`${harness.baseUrl}/api/agents/${body.agentId}`, {
headers: harness.headers,
@@ -170,7 +170,7 @@ describe("recursive org execution", () => {
it("routes cross-department hires to the relevant department lead when reportsTo is omitted", async () => {
const harness = await createHarness();
try {
const hrId = harness.db.agents.saveAgent({
const hrId = harness.db.core.agents.saveAgent({
companyId: harness.companyId,
name: "HR Director",
role: "HR Director",
@@ -184,7 +184,7 @@ describe("recursive org execution", () => {
budgetMonthlyUsd: 180,
department: "hr",
});
const hrTaskId = harness.db.tasks.saveTask({
const hrTaskId = harness.db.core.tasks.saveTask({
companyId: harness.companyId,
title: "Fill engineering gap",
description: "Request a backend engineer for the engineering team.",
@@ -193,7 +193,7 @@ describe("recursive org execution", () => {
priority: "high",
status: "in_progress",
});
const hrRun = harness.db.runs.createRun({
const hrRun = harness.db.core.runs.createRun({
companyId: harness.companyId,
taskId: hrTaskId,
agentId: hrId,
@@ -224,7 +224,7 @@ describe("recursive org execution", () => {
expect(response.status).toBe(201);
const body = await response.json() as { agentId: string };
const pendingHire = harness.db.entityCrud.getAgent(body.agentId);
const pendingHire = harness.db.core.entity.getAgent(body.agentId);
expect(pendingHire.department).toBe("engineering");
expect(pendingHire.reportsTo).toBe(harness.ctoId);
} finally {
@@ -264,7 +264,7 @@ describe("recursive org execution", () => {
it("manager cannot route a hire outside their reporting branch", async () => {
const harness = await createHarness();
try {
const cmoId = harness.db.agents.saveAgent({
const cmoId = harness.db.core.agents.saveAgent({
companyId: harness.companyId,
name: "CMO",
role: "CMO",
+7 -7
View File
@@ -25,8 +25,8 @@ async function createHarness() {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.company.saveCompany({ name: "Orbit Foundry", description: "API test", status: "active" });
const workspaceId = db.workspacesMod.saveWorkspace({
const companyId = db.core.company.saveCompany({ name: "Orbit Foundry", description: "API test", status: "active" });
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -34,7 +34,7 @@ async function createHarness() {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "Helios",
role: "CEO",
@@ -47,7 +47,7 @@ async function createHarness() {
capabilities: "Operate the company",
budgetMonthlyUsd: 100,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Ship the API",
description: "Capture structured run events.",
@@ -56,7 +56,7 @@ async function createHarness() {
priority: "high",
status: "todo",
});
const run = db.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "openai-codex" });
const run = db.core.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "openai-codex" });
const token = createAgentToken(agentId, companyId, run.id);
const server = createApiServer(db, createTestApiServerCallbacks());
const port = await server.start();
@@ -96,7 +96,7 @@ describe("run event API", () => {
it("returns persisted run events for the active run token", async () => {
const harness = await createHarness();
try {
harness.db.runs.appendRunEvent({
harness.db.core.runs.appendRunEvent({
companyId: harness.companyId,
runId: harness.runId,
agentId: harness.agentId,
@@ -142,7 +142,7 @@ describe("run event API", () => {
expect(reader).toBeDefined();
setTimeout(() => {
harness.db.runs.appendRunEvent({
harness.db.core.runs.appendRunEvent({
companyId: harness.companyId,
runId: harness.runId,
agentId: harness.agentId,
@@ -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.approvalsMod.requestApproval({
const approvalId = shared.db.core.approvals.requestApproval({
companyId: shared.companyId,
requestedByAgentId: ceoId,
type: "hire_agent",
@@ -23,13 +23,13 @@ describe("Step 4: Hire approval + decideApproval", () => {
payloadJson: JSON.stringify({ agentId: hireId }),
});
shared.db.approvalsMod.decideApproval({
shared.db.core.approvals.decideApproval({
approvalId,
state: "approved",
decisionNote: "Approved by board",
});
const updatedAgent = shared.db.entityCrud.getAgent(hireId);
const updatedAgent = shared.db.core.entity.getAgent(hireId);
expect(updatedAgent.status).toBe("idle");
});
@@ -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.approvalsMod.requestApproval({
const approvalId = shared.db.core.approvals.requestApproval({
companyId: shared.companyId,
requestedByAgentId: ceoId,
type: "hire_agent",
@@ -46,20 +46,20 @@ describe("Step 4: Hire approval + decideApproval", () => {
payloadJson: JSON.stringify({ agentId: hireId }),
});
shared.db.approvalsMod.decideApproval({
shared.db.core.approvals.decideApproval({
approvalId,
state: "rejected",
decisionNote: "Not needed",
});
const updatedAgent = shared.db.entityCrud.getAgent(hireId);
const updatedAgent = shared.db.core.entity.getAgent(hireId);
expect(updatedAgent.status).toBe("terminated");
});
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.approvalsMod.requestApproval({
const approvalId = shared.db.core.approvals.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.approvalsMod.getApprovalRecord(approvalId);
const approval = shared.db.core.approvals.getApprovalRecord(approvalId);
expect(approval.payloadJson).toBeTruthy();
const payload = JSON.parse(approval.payloadJson!);
expect(payload.agentId).toBe(hireId);
@@ -11,7 +11,7 @@ const { createAgent } = shared;
describe("Automation Rules CRUD", () => {
it("creates, reads, toggles, and deletes an automation rule", () => {
const ruleId = shared.db.automationMod.saveAutomationRule({
const ruleId = shared.db.automation.rules.saveAutomationRule({
companyId: shared.companyId,
name: "Auto-escalate blocked tasks",
description: "When a task is blocked, notify the manager",
@@ -28,7 +28,7 @@ describe("Automation Rules CRUD", () => {
expect(ruleId).toBeTruthy();
// Rule appears in snapshot
const snapshot = shared.db.snap.listSnapshot();
const snapshot = shared.db.projection.snapshot.listSnapshot();
const rule = snapshot.automationRules.find(r => r.id === ruleId);
expect(rule).toBeTruthy();
expect(rule!.name).toBe("Auto-escalate blocked tasks");
@@ -39,36 +39,36 @@ describe("Automation Rules CRUD", () => {
expect(rule!.executionCount).toBe(0);
// Toggle to paused
shared.db.automationMod.toggleAutomationRule(ruleId, shared.companyId, "paused");
const updated = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
shared.db.automation.rules.toggleAutomationRule(ruleId, shared.companyId, "paused");
const updated = shared.db.projection.snapshot.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(updated!.status).toBe("paused");
// Record execution
shared.db.automationMod.recordAutomationExecution(ruleId, shared.companyId, "Auto-escalate blocked tasks", "task_blocked", "escalate_to_manager", "Escalated task-123");
const afterExec = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
shared.db.automation.rules.recordAutomationExecution(ruleId, shared.companyId, "Auto-escalate blocked tasks", "task_blocked", "escalate_to_manager", "Escalated task-123");
const afterExec = shared.db.projection.snapshot.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(afterExec!.executionCount).toBe(1);
expect(afterExec!.lastExecutedAt).toBeTruthy();
// Automation log
const log = shared.db.automationMod.getAutomationLog(shared.companyId);
const log = shared.db.automation.rules.getAutomationLog(shared.companyId);
expect(log).toHaveLength(1);
expect(log[0].ruleName).toBe("Auto-escalate blocked tasks");
// Delete
shared.db.automationMod.deleteAutomationRule(ruleId, shared.companyId);
const afterDelete = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
shared.db.automation.rules.deleteAutomationRule(ruleId, shared.companyId);
const afterDelete = shared.db.projection.snapshot.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(afterDelete).toBeUndefined();
});
it("updates an existing rule", () => {
const ruleId = shared.db.automationMod.saveAutomationRule({
const ruleId = shared.db.automation.rules.saveAutomationRule({
companyId: shared.companyId,
name: "Original name",
trigger: "task_created",
action: "assign_task",
});
shared.db.automationMod.saveAutomationRule({
shared.db.automation.rules.saveAutomationRule({
id: ruleId,
companyId: shared.companyId,
name: "Updated name",
@@ -77,7 +77,7 @@ describe("Automation Rules CRUD", () => {
priority: 90,
});
const rule = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
const rule = shared.db.projection.snapshot.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(rule!.name).toBe("Updated name");
expect(rule!.action).toBe("notify_agent");
expect(rule!.priority).toBe(90);
@@ -89,13 +89,13 @@ describe("Agent Messages", () => {
let agentBId: string;
beforeEach(() => {
agentAId = shared.db.agents.saveAgent({
agentAId = shared.db.core.agents.saveAgent({
companyId: shared.companyId, name: "Alice", role: "Engineer", title: "Senior Engineer",
department: "engineering", connectorId: "claude-pro", status: "active",
capabilities: "Backend development, API design, code review",
budgetMonthlyUsd: 100,
});
agentBId = shared.db.agents.saveAgent({
agentBId = shared.db.core.agents.saveAgent({
companyId: shared.companyId, name: "Bob", role: "Designer", title: "UX Designer",
department: "design", connectorId: "claude-pro", status: "active",
capabilities: "UI design, wireframing, user research",
@@ -104,7 +104,7 @@ describe("Agent Messages", () => {
});
it("sends and retrieves direct messages", () => {
const msgId = shared.db.messages.sendAgentMessage({
const msgId = shared.db.core.messages.sendAgentMessage({
companyId: shared.companyId,
fromAgentId: agentAId,
toAgentId: agentBId,
@@ -116,7 +116,7 @@ describe("Agent Messages", () => {
expect(msgId).toBeTruthy();
const messages = shared.db.messages.listAgentMessages(shared.companyId);
const messages = shared.db.core.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.messages.sendAgentMessage({
const msgId = shared.db.core.messages.sendAgentMessage({
companyId: shared.companyId,
fromAgentId: agentAId,
toAgentId: agentBId,
@@ -133,14 +133,14 @@ describe("Agent Messages", () => {
body: "Hello",
});
shared.db.messages.markMessageReadForReader(msgId, shared.companyId);
const messages = shared.db.messages.listAgentMessages(shared.companyId);
shared.db.core.messages.markMessageReadForReader(msgId, shared.companyId);
const messages = shared.db.core.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.messages.sendAgentMessage({
const msgId = shared.db.core.messages.sendAgentMessage({
companyId: shared.companyId,
fromAgentId: agentAId,
toAgentId: agentBId,
@@ -148,22 +148,22 @@ describe("Agent Messages", () => {
body: "Hello",
});
const senderView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: agentAId });
const senderView = shared.db.core.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.messages.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true });
const recipientViewBefore = shared.db.core.messages.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true });
expect(recipientViewBefore).toHaveLength(1);
expect(recipientViewBefore[0].id).toBe(msgId);
shared.db.messages.markMessageReadForReader(msgId, shared.companyId, agentBId);
shared.db.core.messages.markMessageReadForReader(msgId, shared.companyId, agentBId);
const recipientViewAfter = shared.db.messages.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true });
const recipientViewAfter = shared.db.core.messages.listAgentMessages(shared.companyId, { agentId: agentBId, unreadOnly: true });
expect(recipientViewAfter).toHaveLength(0);
const thirdAgentId = createAgent({ name: "Agent C" });
const thirdView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: thirdAgentId });
const thirdView = shared.db.core.messages.listAgentMessages(shared.companyId, { agentId: thirdAgentId });
expect(thirdView).toHaveLength(0);
});
@@ -171,14 +171,14 @@ describe("Agent Messages", () => {
const engineeringLeadId = createAgent({ name: "Engineering Lead", role: "Lead", department: "engineering" });
const productLeadId = createAgent({ name: "Product Lead", role: "Lead", department: "product" });
const projectId = shared.db.entityCrud.saveProject({
const projectId = shared.db.core.entity.saveProject({
companyId: shared.companyId,
name: "Cross-team Project",
description: "Scope",
leadAgentId: engineeringLeadId,
status: "active",
});
shared.db.tasks.saveTask({
shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Project task",
description: "Do work",
@@ -188,7 +188,7 @@ describe("Agent Messages", () => {
priority: "medium",
});
const deptMessageId = shared.db.messages.sendAgentMessage({
const deptMessageId = shared.db.core.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.messages.sendAgentMessage({
const projectMessageId = shared.db.core.messages.sendAgentMessage({
companyId: shared.companyId,
fromAgentId: engineeringLeadId,
channel: "project",
@@ -205,31 +205,31 @@ describe("Agent Messages", () => {
body: "Only project members should see this",
});
const engineeringView = shared.db.messages.listAgentMessages(shared.companyId, { agentId: engineeringLeadId });
const engineeringView = shared.db.core.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.messages.listAgentMessages(shared.companyId, { agentId: productLeadId });
const productView = shared.db.core.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.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" });
shared.db.core.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, subject: "Dept update", body: "All good", channel: "department", channelTargetId: "engineering" });
shared.db.core.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, toAgentId: agentBId, subject: "DM", body: "Hey", channel: "direct" });
const deptMsgs = shared.db.messages.listAgentMessages(shared.companyId, { channel: "department" });
const deptMsgs = shared.db.core.messages.listAgentMessages(shared.companyId, { channel: "department" });
expect(deptMsgs).toHaveLength(1);
expect(deptMsgs[0].subject).toBe("Dept update");
const directMsgs = shared.db.messages.listAgentMessages(shared.companyId, { channel: "direct" });
const directMsgs = shared.db.core.messages.listAgentMessages(shared.companyId, { channel: "direct" });
expect(directMsgs).toHaveLength(1);
expect(directMsgs[0].subject).toBe("DM");
});
it("appears in snapshot", () => {
shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, channel: "company", subject: "Snapshot test", body: "Hi" });
const snapshot = shared.db.snap.listSnapshot();
shared.db.core.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, channel: "company", subject: "Snapshot test", body: "Hi" });
const snapshot = shared.db.projection.snapshot.listSnapshot();
expect(snapshot.agentMessages.length).toBeGreaterThanOrEqual(1);
expect(snapshot.agentMessages[0].subject).toBe("Snapshot test");
});
@@ -240,13 +240,13 @@ describe("Auto Task Assignment", () => {
let frontendId: string;
beforeEach(() => {
backendId = shared.db.agents.saveAgent({
backendId = shared.db.core.agents.saveAgent({
companyId: shared.companyId, name: "Backend Dev", role: "Backend Engineer", title: "Senior Backend",
department: "engineering", connectorId: "openai-codex", status: "active",
capabilities: "API development, database design, Node.js, PostgreSQL, backend testing",
budgetMonthlyUsd: 200,
});
frontendId = shared.db.agents.saveAgent({
frontendId = shared.db.core.agents.saveAgent({
companyId: shared.companyId, name: "Frontend Dev", role: "Frontend Engineer", title: "Senior Frontend",
department: "engineering", connectorId: "openai-codex", status: "active",
capabilities: "React, TypeScript, CSS, Tailwind, responsive design, frontend testing, UI components",
@@ -255,68 +255,68 @@ describe("Auto Task Assignment", () => {
});
it("assigns to the best-matching agent by capability keywords", () => {
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId, title: "Build React component for user dashboard",
description: "Create a responsive React component with Tailwind CSS styling",
priority: "medium", status: "todo",
});
const assignedId = shared.db.tasks.autoAssignTask(taskId, shared.companyId);
const assignedId = shared.db.core.tasks.autoAssignTask(taskId, shared.companyId);
expect(assignedId).toBe(frontendId); // "React", "responsive", "Tailwind" match frontend
});
it("assigns backend task to backend agent", () => {
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId, title: "Design database schema for orders",
description: "PostgreSQL database design with API endpoints for order management",
priority: "high", status: "todo",
});
const assignedId = shared.db.tasks.autoAssignTask(taskId, shared.companyId);
const assignedId = shared.db.core.tasks.autoAssignTask(taskId, shared.companyId);
expect(assignedId).toBe(backendId); // "database", "PostgreSQL", "API" match backend
});
it("returns existing assignee if task already assigned", () => {
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId, title: "Already assigned task",
description: "This task has an assignee",
assigneeAgentId: frontendId,
priority: "medium", status: "todo",
});
const result = shared.db.tasks.autoAssignTask(taskId, shared.companyId);
const result = shared.db.core.tasks.autoAssignTask(taskId, shared.companyId);
expect(result).toBe(frontendId);
});
it("returns null if all agents have exhausted their budget", () => {
// Set positive budgets that are fully spent
shared.db.agents.saveAgent({ id: backendId, companyId: shared.companyId, name: "Backend Dev", role: "Backend", title: "Backend", connectorId: "openai-codex", status: "active", capabilities: "backend", budgetMonthlyUsd: 100 });
shared.db.agents.saveAgent({ id: frontendId, companyId: shared.companyId, name: "Frontend Dev", role: "Frontend", title: "Frontend", connectorId: "openai-codex", status: "active", capabilities: "frontend", budgetMonthlyUsd: 100 });
shared.db.core.agents.saveAgent({ id: backendId, companyId: shared.companyId, name: "Backend Dev", role: "Backend", title: "Backend", connectorId: "openai-codex", status: "active", capabilities: "backend", budgetMonthlyUsd: 100 });
shared.db.core.agents.saveAgent({ id: frontendId, companyId: shared.companyId, name: "Frontend Dev", role: "Frontend", title: "Frontend", connectorId: "openai-codex", status: "active", capabilities: "frontend", budgetMonthlyUsd: 100 });
// Exhaust budgets by recording spending via direct SQL (since finishRun would need a real run)
(shared.db as unknown as { db: { prepare: (sql: string) => { run: (...args: unknown[]) => void } } }).db.prepare("update agents set spent_monthly_usd = 100 where id = ?").run(backendId);
(shared.db as unknown as { db: { prepare: (sql: string) => { run: (...args: unknown[]) => void } } }).db.prepare("update agents set spent_monthly_usd = 100 where id = ?").run(frontendId);
const taskId = shared.db.tasks.saveTask({ companyId: shared.companyId, title: "No budget task", description: "Test", priority: "low", status: "todo" });
const result = shared.db.tasks.autoAssignTask(taskId, shared.companyId);
const taskId = shared.db.core.tasks.saveTask({ companyId: shared.companyId, title: "No budget task", description: "Test", priority: "low", status: "todo" });
const result = shared.db.core.tasks.autoAssignTask(taskId, shared.companyId);
expect(result).toBeNull();
});
it("penalizes agents with many active tasks", () => {
// Give backend agent 5 active tasks
for (let i = 0; i < 5; i++) {
shared.db.tasks.saveTask({ companyId: shared.companyId, title: `Backend task ${i}`, description: "", assigneeAgentId: backendId, priority: "medium", status: "in_progress" });
shared.db.core.tasks.saveTask({ companyId: shared.companyId, title: `Backend task ${i}`, description: "", assigneeAgentId: backendId, priority: "medium", status: "in_progress" });
}
// Generic task with no strong keyword match — should go to less busy frontend agent
const taskId = shared.db.tasks.saveTask({ companyId: shared.companyId, title: "Implement feature", description: "Build the feature", priority: "medium", status: "todo" });
const assignedId = shared.db.tasks.autoAssignTask(taskId, shared.companyId);
const taskId = shared.db.core.tasks.saveTask({ companyId: shared.companyId, title: "Implement feature", description: "Build the feature", priority: "medium", status: "todo" });
const assignedId = shared.db.core.tasks.autoAssignTask(taskId, shared.companyId);
expect(assignedId).toBe(frontendId); // Frontend has 0 active tasks vs backend's 5
});
});
describe("Workflow Pipelines", () => {
it("creates, activates, and deletes a workflow", () => {
const wfId = shared.db.automationMod.saveWorkflow({
const wfId = shared.db.automation.rules.saveWorkflow({
companyId: shared.companyId,
name: "Code Review Pipeline",
description: "Auto-review flow for PRs",
@@ -330,14 +330,14 @@ describe("Workflow Pipelines", () => {
});
expect(wfId).toBeTruthy();
const snapshot = shared.db.snap.listSnapshot();
const snapshot = shared.db.projection.snapshot.listSnapshot();
const wf = snapshot.workflows.find(w => w.id === wfId);
expect(wf!.name).toBe("Code Review Pipeline");
expect(wf!.status).toBe("draft");
expect(wf!.runCount).toBe(0);
// Delete
shared.db.automationMod.deleteWorkflow(wfId, shared.companyId);
expect(shared.db.snap.listSnapshot().workflows.find(w => w.id === wfId)).toBeUndefined();
shared.db.automation.rules.deleteWorkflow(wfId, shared.companyId);
expect(shared.db.projection.snapshot.listSnapshot().workflows.find(w => w.id === wfId)).toBeUndefined();
});
});
@@ -36,7 +36,7 @@ describe("Step 2: CEO phased prompts", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const hireId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "pending_approval" as "idle" });
const hire = shared.db.entityCrud.getAgent(hireId);
const hire = shared.db.core.entity.getAgent(hireId);
const ctx = buildCtx({
agentId: ceoId,
@@ -86,7 +86,7 @@ describe("Step 2: CEO phased prompts", () => {
it("Phase 2: shows normal executive instructions when active reports and no pending org approval", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "idle" });
const cto = shared.db.entityCrud.getAgent(ctoId);
const cto = shared.db.core.entity.getAgent(ctoId);
const ctx = buildCtx({
agentId: ceoId,
@@ -107,7 +107,7 @@ describe("Step 2: CEO phased prompts", () => {
it("includes pending approvals section in prompt", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "idle" });
const cto = shared.db.entityCrud.getAgent(ctoId);
const cto = shared.db.core.entity.getAgent(ctoId);
const ctx = buildCtx({
agentId: ceoId,
@@ -137,10 +137,10 @@ describe("Step 2: CEO phased prompts", () => {
it("Manager prompt includes credential escalation guidance", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ceo = shared.db.entityCrud.getAgent(ceoId);
const ceo = shared.db.core.entity.getAgent(ceoId);
const managerId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId });
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: managerId });
const ic = shared.db.entityCrud.getAgent(icId);
const ic = shared.db.core.entity.getAgent(icId);
const ctx = buildCtx({
agentId: managerId,
@@ -154,7 +154,7 @@ describe("Step 2: CEO phased prompts", () => {
it("IC prompt includes credential escalation guidance", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ceo = shared.db.entityCrud.getAgent(ceoId);
const ceo = shared.db.core.entity.getAgent(ceoId);
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: ceoId });
const ctx = buildCtx({
@@ -13,7 +13,7 @@ const { createAgent } = shared;
describe("Step 7: Worker crash recovery (database layer)", () => {
it("interruptStaleRuns clears running and queued runs on init", async () => {
const agentId = createAgent({ name: "Agent" });
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "In-progress task",
description: "Running when crash happened",
@@ -23,7 +23,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
status: "in_progress",
});
const run = shared.db.runs.createRun({
const run = shared.db.core.runs.createRun({
companyId: shared.companyId,
taskId,
agentId,
@@ -31,10 +31,10 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
connectorId: "openai-codex",
});
shared.db.runs.markRunStatus(run.id, "running", "Started");
shared.db.core.runs.markRunStatus(run.id, "running", "Started");
// Verify it's running
let snapshot = shared.db.snap.listSnapshot();
let snapshot = shared.db.projection.snapshot.listSnapshot();
expect(snapshot.runs.find((r) => r.id === run.id)?.status).toBe("running");
// Simulate app restart — close and re-init
@@ -44,14 +44,14 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
shared.db = new AppDatabase(profileDir);
shared.db.init(); // This calls interruptStaleRuns()
snapshot = shared.db.snap.listSnapshot();
snapshot = shared.db.projection.snapshot.listSnapshot();
const recoveredRun = snapshot.runs.find((r) => r.id === run.id);
expect(recoveredRun?.status).toBe("interrupted");
});
it("finishRun can mark interrupted runs from crash recovery", () => {
const agentId = createAgent({ name: "Agent" });
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Crash recovery task",
description: "Test",
@@ -61,7 +61,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
status: "in_progress",
});
const run = shared.db.runs.createRun({
const run = shared.db.core.runs.createRun({
companyId: shared.companyId,
taskId,
agentId,
@@ -69,10 +69,10 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
connectorId: "openai-codex",
});
shared.db.runs.markRunStatus(run.id, "running", "Started");
shared.db.core.runs.markRunStatus(run.id, "running", "Started");
// Simulate crash recovery - mark as interrupted
shared.db.runs.finishRun({
shared.db.core.runs.finishRun({
runId: run.id,
status: "interrupted",
summary: "Worker process crashed.",
@@ -83,7 +83,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
unattributedCost: true,
});
const snapshot = shared.db.snap.listSnapshot();
const snapshot = shared.db.projection.snapshot.listSnapshot();
const recovered = snapshot.runs.find((r) => r.id === run.id);
expect(recovered?.status).toBe("interrupted");
expect(recovered?.errorMessage).toBe("Worker process exited unexpectedly.");
@@ -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.approvalsMod.requestApproval({
const orgApprovalId = shared.db.core.approvals.requestApproval({
companyId: shared.companyId,
requestedByAgentId: ceoId,
type: "approve_ceo_strategy",
@@ -40,8 +40,8 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
});
// CEO now in Phase 1
const ctoRecord = shared.db.entityCrud.getAgent(ctoId);
const cmoRecord = shared.db.entityCrud.getAgent(cmoId);
const ctoRecord = shared.db.core.entity.getAgent(ctoId);
const cmoRecord = shared.db.core.entity.getAgent(cmoId);
const phase1Ctx = buildCtx({
agentId: ceoId,
directReports: [ctoRecord, cmoRecord],
@@ -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.approvalsMod.requestApproval({
const hireApprovalCTO = shared.db.core.approvals.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.approvalsMod.decideApproval({ approvalId: hireApprovalCTO, state: "approved", decisionNote: "Approved" });
shared.db.core.approvals.decideApproval({ approvalId: hireApprovalCTO, state: "approved", decisionNote: "Approved" });
const hireApprovalCMO = shared.db.approvalsMod.requestApproval({
const hireApprovalCMO = shared.db.core.approvals.requestApproval({
companyId: shared.companyId,
requestedByAgentId: ceoId,
type: "hire_agent",
@@ -82,18 +82,18 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
impactSummary: "Test",
payloadJson: JSON.stringify({ agentId: cmoId }),
});
shared.db.approvalsMod.decideApproval({ approvalId: hireApprovalCMO, state: "approved", decisionNote: "Approved" });
shared.db.core.approvals.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");
expect(shared.db.core.entity.getAgent(ctoId).status).toBe("idle");
expect(shared.db.core.entity.getAgent(cmoId).status).toBe("idle");
// 5. Board approves org strategy
shared.db.approvalsMod.decideApproval({ approvalId: orgApprovalId, state: "approved", decisionNote: "Go ahead" });
shared.db.core.approvals.decideApproval({ approvalId: orgApprovalId, state: "approved", decisionNote: "Go ahead" });
// 6. CEO now in Phase 2
const updatedCto = shared.db.entityCrud.getAgent(ctoId);
const updatedCmo = shared.db.entityCrud.getAgent(cmoId);
const updatedCto = shared.db.core.entity.getAgent(ctoId);
const updatedCmo = shared.db.core.entity.getAgent(cmoId);
const phase2Ctx = buildCtx({
agentId: ceoId,
directReports: [updatedCto, updatedCmo],
@@ -106,12 +106,12 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
expect(phase2Prompt).toContain("Delegation");
// 7. Verify hierarchical chain
const ctoChain = shared.db.agents.getChainOfCommand(ctoId);
const ctoChain = shared.db.core.agents.getChainOfCommand(ctoId);
expect(ctoChain).toHaveLength(1);
expect(ctoChain[0].id).toBe(ceoId);
// 8. Create task tree
const projectId = shared.db.entityCrud.saveProject({
const projectId = shared.db.core.entity.saveProject({
companyId: shared.companyId,
name: "Launch MVP",
description: "Build and launch MVP",
@@ -120,7 +120,7 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
status: "in_progress",
});
const parentTaskId = shared.db.tasks.saveTask({
const parentTaskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Build backend",
description: "Implement API",
@@ -133,7 +133,7 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
// CTO creates subtask for IC (would be done via API)
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: ctoId, status: "idle" });
const subtaskId = shared.db.tasks.saveTask({
const subtaskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Implement auth",
description: "JWT auth",
@@ -146,12 +146,12 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
});
// Verify parent-child relationship
const subtask = shared.db.entityCrud.getTask(subtaskId);
const subtask = shared.db.core.entity.getTask(subtaskId);
expect(subtask.parentId).toBe(parentTaskId);
// 9. Wakeup request test: enqueue wake while IC is busy
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, icId, "comment", "comment");
const queuedWakes = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId: icId, status: "queued" });
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, icId, "comment", "comment");
const queuedWakes = shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId: icId, status: "queued" });
expect(queuedWakes).toHaveLength(1);
expect(queuedWakes[0].source).toBe("comment");
@@ -159,7 +159,7 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
const icPromptCtx = buildCtx({
agentId: icId,
task: subtask,
chainOfCommand: [shared.db.entityCrud.getAgent(ctoId), shared.db.entityCrud.getAgent(ceoId)],
chainOfCommand: [shared.db.core.entity.getAgent(ctoId), shared.db.core.entity.getAgent(ceoId)],
wakeReason: "assignment",
});
const icPrompt = buildTaskPrompt(icPromptCtx);
@@ -175,12 +175,12 @@ describe("E2E: Wakeup request lifecycle with run lifecycle", () => {
// Simulate: agent is running, wakes come in. All triggers are coalesced
// into a single wakeup request with JSON array of trigger details.
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "report_blocked", "report_blocked");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "report_blocked", "report_blocked");
// Verify coalesced into single row with all triggers
const wakes = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
const wakes = shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
expect(wakes).toHaveLength(1);
expect(wakes[0].coalescedCount).toBe(2);
@@ -191,7 +191,7 @@ describe("E2E: Wakeup request lifecycle with run lifecycle", () => {
expect(triggers[2].trigger).toBe("report_blocked");
// Wakes remain queued until consumed by the run lifecycle
expect(shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" })).toHaveLength(1);
expect(shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" })).toHaveLength(1);
});
});
@@ -202,11 +202,11 @@ describe("E2E: Blocked escalation through org hierarchy", () => {
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: ctoId });
// When IC marks task blocked, we need to find its manager
const chain = shared.db.agents.getChainOfCommand(icId);
const chain = shared.db.core.agents.getChainOfCommand(icId);
expect(chain[0].id).toBe(ctoId); // immediate manager gets woken
// When CTO needs to escalate further
const ctoChain = shared.db.agents.getChainOfCommand(ctoId);
const ctoChain = shared.db.core.agents.getChainOfCommand(ctoId);
expect(ctoChain[0].id).toBe(ceoId);
});
});
@@ -216,7 +216,7 @@ describe("Review Fix: CEO phase ordering edge case", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
// Hires submitted but not yet approved
const hireId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "pending_approval" as "idle" });
const hire = shared.db.entityCrud.getAgent(hireId);
const hire = shared.db.core.entity.getAgent(hireId);
// Org strategy already approved (not in pendingApprovals), but hires still pending
const ctx = buildCtx({
@@ -236,7 +236,7 @@ describe("Review Fix: CEO phase ordering edge case", () => {
it("moves to Phase 2 once hires are approved (no pending org approval)", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId, status: "idle" });
const cto = shared.db.entityCrud.getAgent(ctoId);
const cto = shared.db.core.entity.getAgent(ctoId);
const ctx = buildCtx({
agentId: ceoId,
@@ -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.approvalsMod.requestApproval({
const approvalId = shared.db.core.approvals.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.approvalsMod.decideApproval({
shared.db.core.approvals.decideApproval({
approvalId,
state: "rejected",
decisionNote: "Not ready",
});
// Verify approval state
const approval = shared.db.approvalsMod.getApprovalRecord(approvalId);
const approval = shared.db.core.approvals.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
@@ -315,7 +315,7 @@ describe("Review Fix: Root task completion notification", () => {
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId });
// CTO has a root-level task (no parentId)
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Standalone task from CEO",
description: "No parent",
@@ -325,11 +325,11 @@ describe("Review Fix: Root task completion notification", () => {
status: "done",
});
const task = shared.db.entityCrud.getTask(taskId);
const task = shared.db.core.entity.getTask(taskId);
expect(task.parentId).toBeNull();
// CTO's chain of command includes CEO — so api-server can wake CEO on completion
const chain = shared.db.agents.getChainOfCommand(ctoId);
const chain = shared.db.core.agents.getChainOfCommand(ctoId);
expect(chain).toHaveLength(1);
expect(chain[0].id).toBe(ceoId);
});
@@ -31,9 +31,9 @@ describe("Step 1: CEO role detection", () => {
it("identifies manager when has reports and has chain of command", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const managerId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId });
const ceo = shared.db.entityCrud.getAgent(ceoId);
const ceo = shared.db.core.entity.getAgent(ceoId);
const icId = createAgent({ name: "IC", role: "Engineer", reportsTo: managerId });
const ic = shared.db.entityCrud.getAgent(icId);
const ic = shared.db.core.entity.getAgent(icId);
const ctx = buildCtx({
agentId: managerId,
@@ -49,7 +49,7 @@ describe("Step 1: CEO role detection", () => {
it("identifies IC when has chain of command and no direct reports", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ceo = shared.db.entityCrud.getAgent(ceoId);
const ceo = shared.db.core.entity.getAgent(ceoId);
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: ceoId });
const ctx = buildCtx({
@@ -12,7 +12,7 @@ const { createAgent } = shared;
describe("Step 6: Run failure escalation (database layer)", () => {
it("finishRun marks run as failed and returns outcome", () => {
const agentId = createAgent({ name: "IC", role: "Engineer" });
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Failing task",
description: "Will fail",
@@ -22,7 +22,7 @@ describe("Step 6: Run failure escalation (database layer)", () => {
status: "in_progress",
});
const run = shared.db.runs.createRun({
const run = shared.db.core.runs.createRun({
companyId: shared.companyId,
taskId,
agentId,
@@ -30,9 +30,9 @@ describe("Step 6: Run failure escalation (database layer)", () => {
connectorId: "openai-codex",
});
shared.db.runs.markRunStatus(run.id, "running", "Started");
shared.db.core.runs.markRunStatus(run.id, "running", "Started");
const outcome = shared.db.runs.finishRun({
const outcome = shared.db.core.runs.finishRun({
runId: run.id,
status: "failed",
summary: null,
@@ -45,7 +45,7 @@ describe("Step 6: Run failure escalation (database layer)", () => {
expect(outcome.budgetHardStopped).toBe(false);
const snapshot = shared.db.snap.listSnapshot();
const snapshot = shared.db.projection.snapshot.listSnapshot();
const finishedRun = snapshot.runs.find((r) => r.id === run.id);
expect(finishedRun?.status).toBe("failed");
expect(finishedRun?.errorMessage).toBe("Process crashed");
@@ -56,7 +56,7 @@ describe("Step 6: Run failure escalation (database layer)", () => {
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId });
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: ctoId });
const chain = shared.db.agents.getChainOfCommand(icId);
const chain = shared.db.core.agents.getChainOfCommand(icId);
// First in chain is the immediate manager (CTO)
expect(chain.length).toBeGreaterThan(0);
expect(chain[0].name).toBe("CTO");
@@ -30,7 +30,7 @@ export interface SharedHandle {
set db(value: AppDatabase);
get companyId(): string;
get workspaceId(): string;
createAgent(overrides?: Partial<Parameters<AppDatabase["agents"]["saveAgent"]>[0]>): string;
createAgent(overrides?: Partial<Parameters<AppDatabase["core"]["agents"]["saveAgent"]>[0]>): string;
buildCtx(overrides?: Record<string, unknown>): Parameters<typeof buildSystemPrompt>[0];
tempDirs: string[];
}
@@ -54,13 +54,13 @@ export function installSharedSetup(): SharedHandle {
state.db = new AppDatabase(profileDir);
state.db.init();
state.companyId = state.db.company.saveCompany({
state.companyId = state.db.core.company.saveCompany({
name: "Autonomous Test Corp",
description: "Test company for autonomous chain",
status: "active",
});
state.workspaceId = state.db.workspacesMod.saveWorkspace({
state.workspaceId = state.db.core.workspaces.saveWorkspace({
companyId: state.companyId,
name: "Primary",
localPath: profileDir,
@@ -80,8 +80,8 @@ export function installSharedSetup(): SharedHandle {
return state.db;
}
function createAgent(overrides: Partial<Parameters<AppDatabase["agents"]["saveAgent"]>[0]> = {}): string {
return currentDb().agents.saveAgent({
function createAgent(overrides: Partial<Parameters<AppDatabase["core"]["agents"]["saveAgent"]>[0]> = {}): string {
return currentDb().core.agents.saveAgent({
companyId: state.companyId,
name: "TestAgent",
role: "CEO",
@@ -98,7 +98,7 @@ export function installSharedSetup(): SharedHandle {
}
function buildCtx(overrides: Record<string, unknown> = {}): Parameters<typeof buildSystemPrompt>[0] {
const agent = currentDb().entityCrud.getAgent(overrides.agentId as string ?? createAgent());
const agent = currentDb().core.entity.getAgent(overrides.agentId as string ?? createAgent());
return {
agent,
apiUrl: "http://127.0.0.1:3000",
@@ -15,7 +15,7 @@ describe("Step 5: Task status + comment wake propagation", () => {
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId });
const icId = createAgent({ name: "Dev", role: "Engineer", reportsTo: ctoId });
const chain = shared.db.agents.getChainOfCommand(icId);
const chain = shared.db.core.agents.getChainOfCommand(icId);
expect(chain).toHaveLength(2);
expect(chain[0].id).toBe(ctoId); // immediate manager
expect(chain[1].id).toBe(ceoId); // top level
@@ -25,7 +25,7 @@ describe("Step 5: Task status + comment wake propagation", () => {
// Create a potential cycle (shouldn't happen in practice, but guard against it)
const agent1 = createAgent({ name: "Agent1" });
// agent1 reports to no one (CEO), so chain should be empty
const chain = shared.db.agents.getChainOfCommand(agent1);
const chain = shared.db.core.agents.getChainOfCommand(agent1);
expect(chain).toHaveLength(0);
});
@@ -33,7 +33,7 @@ describe("Step 5: Task status + comment wake propagation", () => {
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ctoId = createAgent({ name: "CTO", role: "CTO", reportsTo: ceoId });
const parentTaskId = shared.db.tasks.saveTask({
const parentTaskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Build feature X",
description: "Top-level task",
@@ -43,7 +43,7 @@ describe("Step 5: Task status + comment wake propagation", () => {
status: "in_progress",
});
const childTaskId = shared.db.tasks.saveTask({
const childTaskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Implement module A",
description: "Subtask",
@@ -54,10 +54,10 @@ describe("Step 5: Task status + comment wake propagation", () => {
status: "todo",
});
const childTask = shared.db.entityCrud.getTask(childTaskId);
const childTask = shared.db.core.entity.getTask(childTaskId);
expect(childTask.parentId).toBe(parentTaskId);
const parentTask = shared.db.entityCrud.getTask(parentTaskId);
const parentTask = shared.db.core.entity.getTask(parentTaskId);
expect(parentTask.assigneeAgentId).toBe(ctoId);
});
});
@@ -14,7 +14,7 @@ describe("Step 8: Wake reason injection", () => {
it("includes wake reason section for non-timer triggers", () => {
const agentId = createAgent({ name: "CTO", role: "CTO" });
const ceoId = createAgent({ name: "CEO", role: "CEO" });
const ceo = shared.db.entityCrud.getAgent(ceoId);
const ceo = shared.db.core.entity.getAgent(ceoId);
const ctx = buildCtx({
agentId,
@@ -92,7 +92,7 @@ describe("Step 8: Wake reason injection", () => {
it("includes wake reason before task description", () => {
const agentId = createAgent({ name: "Agent" });
const taskId = shared.db.tasks.saveTask({
const taskId = shared.db.core.tasks.saveTask({
companyId: shared.companyId,
title: "Do the thing",
description: "Test task",
@@ -101,7 +101,7 @@ describe("Step 8: Wake reason injection", () => {
priority: "medium",
status: "todo",
});
const task = shared.db.entityCrud.getTask(taskId);
const task = shared.db.core.entity.getTask(taskId);
const ctx = buildCtx({
agentId,
@@ -15,11 +15,11 @@ describe("Step 3: Wakeup request lifecycle (database)", () => {
// Enqueue two wakes for the same busy agent. Coalesced into one row
// with trigger_detail JSON array containing both triggers.
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
// List returns the coalesced wake
const wakes = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
const wakes = shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
expect(wakes).toHaveLength(1);
expect(wakes[0].companyId).toBe(shared.companyId);
expect(wakes[0].coalescedCount).toBe(1);
@@ -32,7 +32,7 @@ describe("Step 3: Wakeup request lifecycle (database)", () => {
it("returns empty array when no wakeup requests exist", () => {
const agentId = createAgent({ name: "TestAgent" });
const wakes = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
const wakes = shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
expect(wakes).toHaveLength(0);
});
@@ -40,15 +40,15 @@ describe("Step 3: Wakeup request lifecycle (database)", () => {
const agent1 = createAgent({ name: "Agent1" });
const agent2 = createAgent({ name: "Agent2" });
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agent1, "comment", "comment");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agent2, "subtask_completed", "subtask_completed");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agent1, "comment", "comment");
shared.db.automation.wakeup.enqueueWakeupRequest(shared.companyId, agent2, "subtask_completed", "subtask_completed");
const wakes1 = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId: agent1, status: "queued" });
const wakes1 = shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId: agent1, status: "queued" });
expect(wakes1).toHaveLength(1);
expect(wakes1[0].source).toBe("comment");
// Agent2's wake should still be there
const wakes2 = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId: agent2, status: "queued" });
const wakes2 = shared.db.automation.wakeup.listWakeupRequests(shared.companyId, { agentId: agent2, status: "queued" });
expect(wakes2).toHaveLength(1);
expect(wakes2[0].source).toBe("subtask_completed");
});
@@ -57,7 +57,7 @@ function createOrchestrationHarness(db: AppDatabase) {
runDispatch.resolveWorkspace,
runDispatch.getRunEligibilityFailure,
runDispatch.dispatchRunToWorker,
(filter) => db.runs.hasActiveRun(filter),
(filter) => db.core.runs.hasActiveRun(filter),
);
return { deps, taskRunner };
@@ -69,7 +69,7 @@ describe("connector model enforcement", () => {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -77,12 +77,12 @@ describe("connector model enforcement", () => {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Runtime Enforcement Co",
description: "Blocks runs when agent models are disabled",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -90,7 +90,7 @@ describe("connector model enforcement", () => {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "CEO",
role: "CEO",
@@ -103,7 +103,7 @@ describe("connector model enforcement", () => {
capabilities: "Lead the company",
budgetMonthlyUsd: 250,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Run with invalid model",
description: "This task should be blocked because the agent model is disabled.",
@@ -113,7 +113,7 @@ describe("connector model enforcement", () => {
status: "todo",
});
db.settings.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
db.core.settings.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
const { taskRunner } = createOrchestrationHarness(db);
const result = taskRunner.queueTaskRun(taskId, "manual", "board");
@@ -123,7 +123,7 @@ describe("connector model enforcement", () => {
throw new Error("Expected queueTaskRun to reject the disabled model.");
}
expect(result.error.code).toBe("CONNECTOR_MODEL_NOT_ALLOWED");
expect(db.snap.listSnapshot().runs).toHaveLength(0);
expect(db.projection.snapshot.listSnapshot().runs).toHaveLength(0);
db.close();
});
@@ -133,7 +133,7 @@ describe("connector model enforcement", () => {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -141,12 +141,12 @@ describe("connector model enforcement", () => {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Recovered Run Co",
description: "Rejects invalid queued runs during recovery",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -154,7 +154,7 @@ describe("connector model enforcement", () => {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "CEO",
role: "CEO",
@@ -167,7 +167,7 @@ describe("connector model enforcement", () => {
capabilities: "Lead the company",
budgetMonthlyUsd: 250,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Recover queued run",
description: "This queued run should fail on recovery because the model is disabled.",
@@ -177,22 +177,22 @@ describe("connector model enforcement", () => {
status: "todo",
});
const run = db.runs.createRun({
const run = db.core.runs.createRun({
companyId,
taskId,
agentId,
workspaceId,
connectorId: "openai-codex",
});
const checkoutSuccess = db.tasks.checkoutTask(taskId, run.id);
const checkoutSuccess = db.core.tasks.checkoutTask(taskId, run.id);
expect(checkoutSuccess).toBe(true);
db.settings.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
db.core.settings.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
const { taskRunner } = createOrchestrationHarness(db);
taskRunner.resumeQueuedRuns();
const recoveredRun = db.snap.listSnapshot().runs.find((entry) => entry.id === run.id);
const recoveredRun = db.projection.snapshot.listSnapshot().runs.find((entry) => entry.id === run.id);
expect(recoveredRun?.status).toBe("failed");
expect(recoveredRun?.errorMessage).toContain("Connector model is disabled or invalid");
+46 -46
View File
@@ -57,20 +57,20 @@ const mockLogger = {
function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
const connectorId: ConnectorId = "gemini-cli";
db.connectorsCrud.saveConnector({
db.core.connectors.saveConnector({
id: connectorId,
model: "gemini-2.5-pro",
envBindingText: "",
notes: "Non-exempt connector for session rotation tests",
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Pipeline Test Corp",
description: "Cross-subsystem pipeline integration tests",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary Workspace",
localPath: "/tmp/pipeline-test",
@@ -79,7 +79,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "PipelineAgent",
role: "IC",
@@ -93,7 +93,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
budgetMonthlyUsd: 100,
});
const goalId = db.entityCrud.saveGoal({
const goalId = db.core.entity.saveGoal({
companyId,
title: "Implement Authentication",
description: "Build full authentication system",
@@ -101,7 +101,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
status: "active",
});
const projectId = db.entityCrud.saveProject({
const projectId = db.core.entity.saveProject({
companyId,
goalId,
name: "Auth Project",
@@ -112,7 +112,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
});
// Budget policy: company-level with hardStop
const policyId = db.budget.saveBudgetPolicy({
const policyId = db.core.budget.saveBudgetPolicy({
companyId,
scopeType: "company",
scopeId: companyId,
@@ -175,7 +175,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
expect(validation.errors).toHaveLength(0);
// Create the task in the DB
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId: s.companyId,
title: "Build login page",
description:
@@ -187,14 +187,14 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
});
// 2. CAS checkout: create run and checkout task
const { id: runId } = db.runs.createRun({
const { id: runId } = db.core.runs.createRun({
companyId: s.companyId,
taskId,
agentId: s.agentId,
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
const checkoutResult = db.tasks.checkoutTask(taskId, runId);
const checkoutResult = db.core.tasks.checkoutTask(taskId, runId);
expect(checkoutResult).toBe(true);
// 3. Budget gate: verify run is allowed
@@ -207,9 +207,9 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
expect(budgetResult.blockedBy).toHaveLength(0);
// 4. Execute run
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({
db.core.runs.markRunStatus(runId, "running", "Starting");
db.core.runs.recordCostEntry({ runId, companyId: s.companyId, agentId: s.agentId, taskId, connectorId: "gemini-cli", amountUsd: 0.05, unattributed: false });
db.core.runs.finishRun({
runId,
status: "succeeded",
summary: "Login page built with form validation",
@@ -221,7 +221,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
});
// 5. Session management: create session and track usage
const sessionId = db.tasks.createNewSession({
const sessionId = db.core.tasks.createNewSession({
companyId: s.companyId,
agentId: s.agentId,
adapterType: "gemini-cli",
@@ -229,13 +229,13 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
sessionService.accumulateTokenUsage(sessionId, 5000, 2000, runId);
// 6. Verify final state
const run = db.runs.getRun(runId);
const run = db.core.runs.getRun(runId);
expect(run.status).toBe("succeeded");
const task = db.entityCrud.getTask(taskId);
const task = db.core.entity.getTask(taskId);
expect(task.costUsd).toBeGreaterThan(0);
const session = db.tasks.getSessionById(sessionId);
const session = db.core.tasks.getSessionById(sessionId);
expect(session).not.toBeNull();
expect(session!.totalInputTokens).toBe(5000);
expect(session!.totalOutputTokens).toBe(2000);
@@ -254,7 +254,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
it("CAS prevents double checkout within pipeline", () => {
const s = scaffold(db);
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId: s.companyId,
title: "Concurrent Task",
description:
@@ -266,17 +266,17 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
});
// First agent checks out
const { id: runId1 } = db.runs.createRun({
const { id: runId1 } = db.core.runs.createRun({
companyId: s.companyId,
taskId,
agentId: s.agentId,
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
expect(db.tasks.checkoutTask(taskId, runId1)).toBe(true);
expect(db.core.tasks.checkoutTask(taskId, runId1)).toBe(true);
// Second agent creates a run but cannot check out
const agent2Id = db.agents.saveAgent({
const agent2Id = db.core.agents.saveAgent({
companyId: s.companyId,
name: "Agent2",
role: "IC",
@@ -289,14 +289,14 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
capabilities: "Backend development",
budgetMonthlyUsd: 100,
});
const { id: runId2 } = db.runs.createRun({
const { id: runId2 } = db.core.runs.createRun({
companyId: s.companyId,
taskId,
agentId: agent2Id,
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
expect(db.tasks.checkoutTask(taskId, runId2)).toBe(false);
expect(db.core.tasks.checkoutTask(taskId, runId2)).toBe(false);
});
it("budget gate blocks run when policy exhausted", () => {
@@ -311,7 +311,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
});
// Create and complete a run that exceeds the budget
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId: s.companyId,
title: "Expensive Task",
description:
@@ -322,7 +322,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
status: "todo",
});
const { id: runId } = db.runs.createRun({
const { id: runId } = db.core.runs.createRun({
companyId: s.companyId,
taskId,
agentId: s.agentId,
@@ -330,10 +330,10 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
connectorId: s.connectorId,
});
db.tasks.checkoutTask(taskId, runId);
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({
db.core.tasks.checkoutTask(taskId, runId);
db.core.runs.markRunStatus(runId, "running", "Starting");
db.core.runs.recordCostEntry({ runId, companyId: s.companyId, agentId: s.agentId, taskId, connectorId: s.connectorId, amountUsd: 1.5, unattributed: false });
db.core.runs.finishRun({
runId,
status: "succeeded",
summary: "Done",
@@ -363,7 +363,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
logger: mockLogger,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId: s.companyId,
title: "Multi-Run Task",
description:
@@ -375,14 +375,14 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
});
// Create session
const sessionId = db.tasks.createNewSession({
const sessionId = db.core.tasks.createNewSession({
companyId: s.companyId,
agentId: s.agentId,
adapterType: "gemini-cli",
});
// Run 1: create run and accumulate tokens
const { id: runId1 } = db.runs.createRun({
const { id: runId1 } = db.core.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.runs.createRun({
const { id: runId2 } = db.core.runs.createRun({
companyId: s.companyId,
taskId,
agentId: s.agentId,
@@ -402,7 +402,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
sessionService.accumulateTokenUsage(sessionId, 3000, 1000, runId2);
// Verify accumulated session state
const session = db.tasks.getSessionById(sessionId);
const session = db.core.tasks.getSessionById(sessionId);
expect(session).not.toBeNull();
expect(session!.runCount).toBe(2);
expect(session!.totalInputTokens).toBe(8000);
@@ -421,7 +421,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
});
// --- First run: costs $3, budget allows ---
const taskId1 = db.tasks.saveTask({
const taskId1 = db.core.tasks.saveTask({
companyId: s.companyId,
title: "First Pipeline Task",
description:
@@ -432,17 +432,17 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
status: "todo",
});
const { id: runId1 } = db.runs.createRun({
const { id: runId1 } = db.core.runs.createRun({
companyId: s.companyId,
taskId: taskId1,
agentId: s.agentId,
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
db.tasks.checkoutTask(taskId1, runId1);
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({
db.core.tasks.checkoutTask(taskId1, runId1);
db.core.runs.markRunStatus(runId1, "running", "Starting");
db.core.runs.recordCostEntry({ runId: runId1, companyId: s.companyId, agentId: s.agentId, taskId: taskId1, connectorId: s.connectorId, amountUsd: 3.0, unattributed: false });
db.core.runs.finishRun({
runId: runId1,
status: "succeeded",
summary: "First task done",
@@ -462,7 +462,7 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
expect(afterFirst.allowed).toBe(true);
// --- Second run: costs $3, now total = $6 > $5 budget ---
const taskId2 = db.tasks.saveTask({
const taskId2 = db.core.tasks.saveTask({
companyId: s.companyId,
title: "Second Pipeline Task",
description:
@@ -473,17 +473,17 @@ describe("Cross-Subsystem Pipeline (D-04)", () => {
status: "todo",
});
const { id: runId2 } = db.runs.createRun({
const { id: runId2 } = db.core.runs.createRun({
companyId: s.companyId,
taskId: taskId2,
agentId: s.agentId,
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
db.tasks.checkoutTask(taskId2, runId2);
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({
db.core.tasks.checkoutTask(taskId2, runId2);
db.core.runs.markRunStatus(runId2, "running", "Starting");
db.core.runs.recordCostEntry({ runId: runId2, companyId: s.companyId, agentId: s.agentId, taskId: taskId2, connectorId: s.connectorId, amountUsd: 3.0, unattributed: false });
db.core.runs.finishRun({
runId: runId2,
status: "succeeded",
summary: "Second task done",
+30 -30
View File
@@ -37,13 +37,13 @@ describe("AppDatabase", () => {
const db = new AppDatabase(profileDir);
db.init();
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Orbit Foundry",
description: "Test company",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -52,7 +52,7 @@ describe("AppDatabase", () => {
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "Helios",
role: "CEO",
@@ -66,7 +66,7 @@ describe("AppDatabase", () => {
budgetMonthlyUsd: 200,
});
const goalId = db.entityCrud.saveGoal({
const goalId = db.core.entity.saveGoal({
companyId,
title: "Ship the desktop app",
description: "Reach packaged desktop parity.",
@@ -74,7 +74,7 @@ describe("AppDatabase", () => {
status: "active",
});
const projectId = db.entityCrud.saveProject({
const projectId = db.core.entity.saveProject({
companyId,
goalId,
name: "Desktop rebuild",
@@ -83,7 +83,7 @@ describe("AppDatabase", () => {
status: "in_progress",
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
projectId,
goalId,
@@ -95,25 +95,25 @@ describe("AppDatabase", () => {
status: "todo",
});
db.entityCrud.saveSecret({
db.core.entity.saveSecret({
companyId,
name: "vault-openai",
description: "Test key",
value: "sk-test-123",
});
db.connectorsCrud.saveConnector({
db.core.connectors.saveConnector({
id: "openai-codex",
model: null,
envBindingText: "OPENAI_API_KEY=vault-openai",
notes: "Connector note",
});
expect(db.entityCrud.resolveSecretEnv("OPENAI_API_KEY=vault-openai", companyId)).toEqual({
expect(db.core.entity.resolveSecretEnv("OPENAI_API_KEY=vault-openai", companyId)).toEqual({
OPENAI_API_KEY: "sk-test-123",
});
const run = db.runs.createRun({
const run = db.core.runs.createRun({
companyId,
taskId,
agentId,
@@ -121,11 +121,11 @@ describe("AppDatabase", () => {
connectorId: "openai-codex",
});
await db.runs.appendRunLog(run.id, "stdout", "hello from run\n");
expect(db.runs.readRunLog(run.id)).toContain("hello from run");
await db.core.runs.appendRunLog(run.id, "stdout", "hello from run\n");
expect(db.core.runs.readRunLog(run.id)).toContain("hello from run");
db.runs.markRunStatus(run.id, "running", "Connector launched");
db.runs.finishRun({
db.core.runs.markRunStatus(run.id, "running", "Connector launched");
db.core.runs.finishRun({
runId: run.id,
status: "succeeded",
summary: "Completed successfully",
@@ -136,22 +136,22 @@ describe("AppDatabase", () => {
unattributedCost: false,
});
const snapshotBeforeBackup = db.snap.listSnapshot();
const snapshotBeforeBackup = db.projection.snapshot.listSnapshot();
expect(snapshotBeforeBackup.companies).toHaveLength(1);
expect(snapshotBeforeBackup.runs[0]?.status).toBe("succeeded");
expect(snapshotBeforeBackup.tasks[0]?.activeRunId).toBeNull();
await db.backupMod.exportBackup(backupDir);
await db.core.backup.exportBackup(backupDir);
db.company.saveCompany({
db.core.company.saveCompany({
name: "Temporary company",
description: "Should disappear after restore",
status: "active",
});
expect(db.snap.listSnapshot().companies).toHaveLength(2);
expect(db.projection.snapshot.listSnapshot().companies).toHaveLength(2);
await db.backupMod.restoreFromBackup(backupDir);
const restoredSnapshot = db.snap.listSnapshot();
await db.core.backup.restoreFromBackup(backupDir);
const restoredSnapshot = db.projection.snapshot.listSnapshot();
expect(restoredSnapshot.companies).toHaveLength(1);
expect(restoredSnapshot.companies[0]?.name).toBe("Orbit Foundry");
expect(restoredSnapshot.runs[0]?.summary).toBe("Completed successfully");
@@ -164,19 +164,19 @@ describe("AppDatabase", () => {
const db = new AppDatabase(profileDir);
db.init();
const alphaCompanyId = db.company.saveCompany({
const alphaCompanyId = db.core.company.saveCompany({
name: "Alpha",
description: "Alpha company",
status: "active",
});
const betaCompanyId = db.company.saveCompany({
const betaCompanyId = db.core.company.saveCompany({
name: "Beta",
description: "Beta company",
status: "active",
});
const alphaWorkspaceId = db.workspacesMod.saveWorkspace({
const alphaWorkspaceId = db.core.workspaces.saveWorkspace({
companyId: alphaCompanyId,
name: "Alpha Workspace",
localPath: profileDir,
@@ -185,7 +185,7 @@ describe("AppDatabase", () => {
isPrimary: true,
});
const betaWorkspaceId = db.workspacesMod.saveWorkspace({
const betaWorkspaceId = db.core.workspaces.saveWorkspace({
companyId: betaCompanyId,
name: "Beta Workspace",
localPath: profileDir,
@@ -194,7 +194,7 @@ describe("AppDatabase", () => {
isPrimary: true,
});
const alphaAgentId = db.agents.saveAgent({
const alphaAgentId = db.core.agents.saveAgent({
companyId: alphaCompanyId,
name: "Alpha CEO",
role: "CEO",
@@ -208,7 +208,7 @@ describe("AppDatabase", () => {
budgetMonthlyUsd: 100,
});
db.agents.saveAgent({
db.core.agents.saveAgent({
companyId: betaCompanyId,
name: "Beta CEO",
role: "CEO",
@@ -222,7 +222,7 @@ describe("AppDatabase", () => {
budgetMonthlyUsd: 100,
});
db.tasks.saveTask({
db.core.tasks.saveTask({
companyId: alphaCompanyId,
title: "Alpha task",
description: "Alpha work",
@@ -232,7 +232,7 @@ describe("AppDatabase", () => {
status: "todo",
});
db.tasks.saveTask({
db.core.tasks.saveTask({
companyId: betaCompanyId,
title: "Beta task",
description: "Beta work",
@@ -242,9 +242,9 @@ describe("AppDatabase", () => {
status: "todo",
});
db.settings.setCurrentCompany(alphaCompanyId);
db.core.settings.setCurrentCompany(alphaCompanyId);
const rendererSnapshot = db.snap.listRendererSnapshot();
const rendererSnapshot = db.projection.snapshot.listRendererSnapshot();
expect(rendererSnapshot.currentCompanyId).toBe(alphaCompanyId);
expect(rendererSnapshot.companies).toHaveLength(2);
expect(rendererSnapshot.connectors.length).toBeGreaterThan(0);
@@ -27,7 +27,7 @@ async function createHarness() {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -35,12 +35,12 @@ async function createHarness() {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Document Provenance Co",
description: "Tests document revision provenance through run completion",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -48,7 +48,7 @@ async function createHarness() {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "Research Lead",
role: "Researcher",
@@ -61,7 +61,7 @@ async function createHarness() {
capabilities: "Research and synthesis",
budgetMonthlyUsd: 180,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Refresh the market report",
description: "Update the report with new findings and submit it for review.",
@@ -70,9 +70,9 @@ async function createHarness() {
priority: "high",
status: "in_progress",
});
db.tasks.setTaskType(taskId, "research");
db.core.tasks.setTaskType(taskId, "research");
const existingDocumentId = db.documentsMod.saveDocument({
const existingDocumentId = db.core.documents.saveDocument({
companyId,
type: "knowledge_article",
title: "Market report",
@@ -83,7 +83,7 @@ async function createHarness() {
status: "draft",
});
const run = db.runs.createRun({
const run = db.core.runs.createRun({
companyId,
taskId,
agentId,
@@ -150,7 +150,7 @@ describe("document run provenance", () => {
)[0];
expect(updatedDocument?.sourceRunId).toBe(harness.run.id);
const persistedRun = harness.db.snap.listSnapshot().runs.find((entry) => entry.id === harness.run.id);
const persistedRun = harness.db.projection.snapshot.listSnapshot().runs.find((entry) => entry.id === harness.run.id);
if (!persistedRun) {
throw new Error("Expected persisted run record for provenance test.");
}
@@ -173,7 +173,7 @@ describe("document run provenance", () => {
// ai_ceo + top-level CEO without `reviewDeliverables` advances
// straight to `done` — there is no reviewer in that configuration
// so the prior `in_review` state was a dead letter.
const task = harness.db.entityCrud.getTask(harness.taskId);
const task = harness.db.core.entity.getTask(harness.taskId);
expect(task.status).toBe("done");
} finally {
harness.server.stop();
@@ -285,7 +285,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.company.saveCompany({
harness.db.core.company.saveCompany({
id: harness.companyId,
name: "Document Provenance Co",
description: "Tests document review task linkage",
@@ -308,7 +308,7 @@ describe("document run provenance", () => {
);
expect(createResponse.status).toBe(201);
const approvals = harness.db.snap.listSnapshot().approvals.filter((approval) => approval.type === "deliverable_review");
const approvals = harness.db.projection.snapshot.listSnapshot().approvals.filter((approval) => approval.type === "deliverable_review");
expect(approvals).toHaveLength(1);
expect(approvals[0]?.relatedTaskId).toBe(harness.taskId);
} finally {
+15 -15
View File
@@ -52,11 +52,11 @@ function buildKickoffPayload(db: AppDatabase, summary: { companyId: string; lead
throw new Error("Missing lead agent or task in onboarding summary.");
}
const agent = db.entityCrud.getAgent(summary.leadAgentId);
const task = db.entityCrud.getTask(summary.taskId);
const connector = db.connectorsCrud.getConnector(agent.connectorId);
const workspace = summary.workspaceId ? db.workspacesMod.getWorkspace(summary.workspaceId) : null;
const company = db.snap.listSnapshot().companies.find((entry) => entry.id === summary.companyId);
const agent = db.core.entity.getAgent(summary.leadAgentId);
const task = db.core.entity.getTask(summary.taskId);
const connector = db.core.connectors.getConnector(agent.connectorId);
const workspace = summary.workspaceId ? db.core.workspaces.getWorkspace(summary.workspaceId) : null;
const company = db.projection.snapshot.listSnapshot().companies.find((entry) => entry.id === summary.companyId);
if (!company) {
throw new Error(`Company ${summary.companyId} not found in snapshot.`);
@@ -72,7 +72,7 @@ function buildKickoffPayload(db: AppDatabase, summary: { companyId: string; lead
workspaceMode: "exclusive",
companyName: company.name,
companyDescription: company.description,
snapshot: db.snap.listSnapshot(),
snapshot: db.projection.snapshot.listSnapshot(),
trigger: "bootstrap",
}, {
db,
@@ -98,7 +98,7 @@ describe("onboarding model pool integration", () => {
throw new Error("openai-codex requires at least two models for this integration test.");
}
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -125,11 +125,11 @@ describe("onboarding model pool integration", () => {
throw new Error("Expected lead agent id from onboarding bootstrap.");
}
const agent = db.entityCrud.getAgent(summary.leadAgentId);
const agent = db.core.entity.getAgent(summary.leadAgentId);
expect(agent.connectorId).toBe("openai-codex");
expect(agent.model).toBe(enabledModel);
expect(db.settings.getDisabledModels(summary.companyId, "openai-codex")).toEqual([{ id: disabledModel, label: disabledModel }]);
expect(db.settings.getCurrentCompanyId()).toBe(summary.companyId);
expect(db.core.settings.getDisabledModels(summary.companyId, "openai-codex")).toEqual([{ id: disabledModel, label: disabledModel }]);
expect(db.core.settings.getCurrentCompanyId()).toBe(summary.companyId);
const payload = buildKickoffPayload(db, summary);
expect(payload.model).toBe(enabledModel);
@@ -161,7 +161,7 @@ describe("onboarding model pool integration", () => {
throw new Error("anthropic provider must expose at least two models from pi-ai.");
}
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "anthropic",
status: "ready",
authState: "authenticated",
@@ -205,7 +205,7 @@ describe("onboarding model pool integration", () => {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -230,7 +230,7 @@ describe("onboarding model pool integration", () => {
throw new Error("Expected lead agent id from onboarding bootstrap.");
}
const agent = db.entityCrud.getAgent(summary.leadAgentId);
const agent = db.core.entity.getAgent(summary.leadAgentId);
expect(agent.model).toBeNull();
const payload = buildKickoffPayload(db, summary);
@@ -254,7 +254,7 @@ describe("onboarding model pool integration", () => {
throw new Error("openai-codex requires a default and fallback model for reroute testing.");
}
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -296,7 +296,7 @@ describe("onboarding model pool integration", () => {
throw new Error("openai-codex requires a model to validate onboarding rejection.");
}
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
+9 -9
View File
@@ -35,13 +35,13 @@ describe("pi-mono migrations 27 + 28", () => {
const db = new AppDatabase(dir);
db.init();
db.sessionEntries.append({
db.projection.sessionEntries.append({
taskSessionId: "test-session",
kind: "message",
role: "user",
payloadJson: JSON.stringify({ role: "user", content: "hello" }),
});
const rows = db.sessionEntries.listActive("test-session");
const rows = db.projection.sessionEntries.listActive("test-session");
expect(rows).toHaveLength(1);
expect(rows[0]?.kind).toBe("message");
db.close();
@@ -53,7 +53,7 @@ describe("pi-mono migrations 27 + 28", () => {
db.init();
const cipher = db.vault.encrypt(JSON.stringify({ source: "literal", value: "sk-test-1234567890" }));
db.credentialsTable.upsert({
db.core.credentials.upsert({
connectorId: "test-anthropic",
kind: "api_key",
backend: cipher.backend,
@@ -65,7 +65,7 @@ describe("pi-mono migrations 27 + 28", () => {
lastError: null,
});
const rows = db.credentialsTable.list();
const rows = db.core.credentials.list();
expect(rows.some((row) => row.connectorId === "test-anthropic")).toBe(true);
db.close();
});
@@ -74,14 +74,14 @@ describe("pi-mono migrations 27 + 28", () => {
const dir = await freshProfile("agentcompany-migration-idempotent-");
const dbA = new AppDatabase(dir);
dbA.init();
dbA.sessionEntries.append({
dbA.projection.sessionEntries.append({
taskSessionId: "session-x",
kind: "message",
role: "user",
payloadJson: JSON.stringify({ role: "user", content: "first" }),
});
const cipher = dbA.vault.encrypt(JSON.stringify({ source: "literal", value: "sk-keep-me" }));
dbA.credentialsTable.upsert({
dbA.core.credentials.upsert({
connectorId: "test-keep",
kind: "api_key",
backend: cipher.backend,
@@ -96,8 +96,8 @@ describe("pi-mono migrations 27 + 28", () => {
const dbB = new AppDatabase(dir);
dbB.init();
expect(dbB.sessionEntries.listActive("session-x")).toHaveLength(1);
expect(dbB.credentialsTable.list().filter((row) => row.connectorId === "test-keep")).toHaveLength(1);
expect(dbB.projection.sessionEntries.listActive("session-x")).toHaveLength(1);
expect(dbB.core.credentials.list().filter((row) => row.connectorId === "test-keep")).toHaveLength(1);
dbB.close();
});
@@ -106,7 +106,7 @@ describe("pi-mono migrations 27 + 28", () => {
const db = new AppDatabase(dir);
db.init();
const rows = db.snap.listSnapshot().connectors.map((entry) => entry.id);
const rows = db.projection.snapshot.listSnapshot().connectors.map((entry) => entry.id);
expect(rows.length).toBe(26);
expect(rows).toContain("claude-pro");
expect(rows).toContain("amazon-bedrock");
+32 -32
View File
@@ -54,7 +54,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
const connectorId: ConnectorId = "gemini-cli";
// Connector
db.connectorsCrud.saveConnector({
db.core.connectors.saveConnector({
id: connectorId,
model: "gemini-2.5-pro",
envBindingText: "",
@@ -62,14 +62,14 @@ function scaffold(db: AppDatabase): ScaffoldResult {
});
// Company
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Recovery Test Corp",
description: "Process recovery integration tests",
status: "active",
});
// Workspace
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary Workspace",
localPath: "/tmp/recovery-test",
@@ -79,7 +79,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
});
// Agent
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "RecoveryAgent",
role: "IC",
@@ -94,7 +94,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
});
// Goal
const goalId = db.entityCrud.saveGoal({
const goalId = db.core.entity.saveGoal({
companyId,
title: "Build login page",
description: "Implement login page with authentication",
@@ -103,7 +103,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
});
// Project
const projectId = db.entityCrud.saveProject({
const projectId = db.core.entity.saveProject({
companyId,
goalId,
name: "Auth Module",
@@ -145,7 +145,7 @@ function createAndStartRun(
): { runId: string; taskId: string } {
const taskId =
opts.taskId ??
db.tasks.saveTask({
db.core.tasks.saveTask({
companyId: opts.companyId,
title: opts.taskTitle ?? "Test Task",
description:
@@ -157,7 +157,7 @@ function createAndStartRun(
status: "todo",
});
const { id: runId } = db.runs.createRun({
const { id: runId } = db.core.runs.createRun({
companyId: opts.companyId,
taskId,
agentId: opts.agentId,
@@ -165,11 +165,11 @@ function createAndStartRun(
connectorId: opts.connectorId,
});
db.tasks.checkoutTask(taskId, runId);
db.runs.markRunStatus(runId, "running", "Starting execution");
db.core.tasks.checkoutTask(taskId, runId);
db.core.runs.markRunStatus(runId, "running", "Starting execution");
if (opts.claimWorkspace !== false) {
db.workspacesMod.claimWorkspaceLock(opts.workspaceId, runId);
db.core.workspaces.claimWorkspaceLock(opts.workspaceId, runId);
}
// Set agent status to "running" to simulate active execution
@@ -243,7 +243,7 @@ describe("Process Recovery -- Worker Crash Detection", () => {
const s = scaffold(db);
// Create a second agent for a second run
const agent2Id = db.agents.saveAgent({
const agent2Id = db.core.agents.saveAgent({
companyId: s.companyId,
name: "Agent2",
role: "IC",
@@ -278,8 +278,8 @@ describe("Process Recovery -- Worker Crash Detection", () => {
const interruptedCount = simulateWorkerCrash(db);
expect(interruptedCount).toBe(2);
expect(db.runs.getRun(run1.runId).status).toBe("interrupted");
expect(db.runs.getRun(run2.runId).status).toBe("interrupted");
expect(db.core.runs.getRun(run1.runId).status).toBe("interrupted");
expect(db.core.runs.getRun(run2.runId).status).toBe("interrupted");
});
it("releases task locks after crash", () => {
@@ -306,7 +306,7 @@ describe("Process Recovery -- Worker Crash Detection", () => {
// However, after crash, the task is set to "blocked" and a subsequent
// stale lock recovery pass handles the checkout_run_id.
// For this test, verify the task status is blocked (the recovery mechanism).
const task = db.entityCrud.getTask(taskId);
const task = db.core.entity.getTask(taskId);
expect(task.status).toBe("blocked");
});
@@ -320,11 +320,11 @@ describe("Process Recovery -- Worker Crash Detection", () => {
});
// Verify agent is running before crash
expect(db.entityCrud.getAgent(s.agentId).status).toBe("running");
expect(db.core.entity.getAgent(s.agentId).status).toBe("running");
simulateWorkerCrash(db);
expect(db.entityCrud.getAgent(s.agentId).status).toBe("idle");
expect(db.core.entity.getAgent(s.agentId).status).toBe("idle");
});
it("releases workspace locks after crash", () => {
@@ -356,7 +356,7 @@ describe("Process Recovery -- Worker Crash Detection", () => {
expect(wsAfter.lock_holder_run_id).toBeNull();
// Verify we can re-claim the workspace (lock is truly released)
const agent2Id = db.agents.saveAgent({
const agent2Id = db.core.agents.saveAgent({
companyId: s.companyId,
name: "Agent2",
role: "IC",
@@ -369,7 +369,7 @@ describe("Process Recovery -- Worker Crash Detection", () => {
capabilities: "Testing",
budgetMonthlyUsd: 100,
});
const taskId2 = db.tasks.saveTask({
const taskId2 = db.core.tasks.saveTask({
companyId: s.companyId,
title: "Recovery Task",
description: "A recovery task after crash to verify workspace lock is released properly.",
@@ -378,14 +378,14 @@ describe("Process Recovery -- Worker Crash Detection", () => {
priority: "medium",
status: "todo",
});
const { id: newRunId } = db.runs.createRun({
const { id: newRunId } = db.core.runs.createRun({
companyId: s.companyId,
taskId: taskId2,
agentId: agent2Id,
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
expect(db.workspacesMod.claimWorkspaceLock(s.workspaceId, newRunId)).toBe(true);
expect(db.core.workspaces.claimWorkspaceLock(s.workspaceId, newRunId)).toBe(true);
});
it("tasks set to blocked after crash", () => {
@@ -398,12 +398,12 @@ describe("Process Recovery -- Worker Crash Detection", () => {
});
// Verify task is in_progress before crash
expect(db.entityCrud.getTask(taskId).status).toBe("in_progress");
expect(db.core.entity.getTask(taskId).status).toBe("in_progress");
simulateWorkerCrash(db);
// Task should be blocked (prevents heartbeat re-queuing)
expect(db.entityCrud.getTask(taskId).status).toBe("blocked");
expect(db.core.entity.getTask(taskId).status).toBe("blocked");
});
});
@@ -422,12 +422,12 @@ describe("Process Recovery -- Context Preservation (D-02)", () => {
});
// Verify assignment before crash
expect(db.entityCrud.getTask(taskId).assigneeAgentId).toBe(s.agentId);
expect(db.core.entity.getTask(taskId).assigneeAgentId).toBe(s.agentId);
simulateWorkerCrash(db);
// Agent assignment must be preserved for retry context
expect(db.entityCrud.getTask(taskId).assigneeAgentId).toBe(s.agentId);
expect(db.core.entity.getTask(taskId).assigneeAgentId).toBe(s.agentId);
});
it("session handoff markdown generated on crash", () => {
@@ -440,7 +440,7 @@ describe("Process Recovery -- Context Preservation (D-02)", () => {
});
// Create a task session (simulating what happens during normal execution)
const sessionId = db.tasks.createNewSession({
const sessionId = db.core.tasks.createNewSession({
companyId: s.companyId,
agentId: s.agentId,
adapterType: "gemini-cli",
@@ -448,7 +448,7 @@ describe("Process Recovery -- Context Preservation (D-02)", () => {
// Drive the session past the maxRuns=20 threshold so rotation fires.
for (let i = 0; i < 20; i++) {
db.tasks.incrementSessionUsage(sessionId, 1000, 500, `${runId}-${i}`);
db.core.tasks.incrementSessionUsage(sessionId, 1000, 500, `${runId}-${i}`);
}
const sessionService = createSessionManagementService({
@@ -456,7 +456,7 @@ describe("Process Recovery -- Context Preservation (D-02)", () => {
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
});
const session = db.tasks.getSessionById(sessionId);
const session = db.core.tasks.getSessionById(sessionId);
expect(session).not.toBeNull();
const rotationResult = sessionService.evaluateRotation(session!);
@@ -499,7 +499,7 @@ describe("Process Recovery -- Multiple Concurrent Runs", () => {
const agents = [s.agentId];
for (let i = 2; i <= 3; i++) {
agents.push(
db.agents.saveAgent({
db.core.agents.saveAgent({
companyId: s.companyId,
name: `Agent${i}`,
role: "IC",
@@ -530,7 +530,7 @@ describe("Process Recovery -- Multiple Concurrent Runs", () => {
expect(interruptedCount).toBe(3);
for (const run of runs) {
expect(db.runs.getRun(run.runId).status).toBe("interrupted");
expect(db.core.runs.getRun(run.runId).status).toBe("interrupted");
}
});
@@ -540,7 +540,7 @@ describe("Process Recovery -- Multiple Concurrent Runs", () => {
const agents = [s.agentId];
for (let i = 2; i <= 3; i++) {
agents.push(
db.agents.saveAgent({
db.core.agents.saveAgent({
companyId: s.companyId,
name: `Agent${i}`,
role: "IC",
@@ -571,7 +571,7 @@ describe("Process Recovery -- Multiple Concurrent Runs", () => {
// All tasks should be blocked (crash recovery sets them to blocked)
for (const run of runs) {
const task = db.entityCrud.getTask(run.taskId);
const task = db.core.entity.getTask(run.taskId);
expect(task.status).toBe("blocked");
}
@@ -24,7 +24,7 @@ describe("skill-aware capability registry", () => {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -32,12 +32,12 @@ describe("skill-aware capability registry", () => {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Skill Match Co",
description: "Tests skill-aware assignment",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -46,7 +46,7 @@ describe("skill-aware capability registry", () => {
isPrimary: true,
});
db.agents.saveAgent({
db.core.agents.saveAgent({
companyId,
name: "Generic Engineer",
role: "Engineer",
@@ -59,7 +59,7 @@ describe("skill-aware capability registry", () => {
capabilities: "General software delivery",
budgetMonthlyUsd: 200,
});
const styledEngineerId = db.agents.saveAgent({
const styledEngineerId = db.core.agents.saveAgent({
companyId,
name: "Frontend Specialist",
role: "Engineer",
@@ -75,7 +75,7 @@ describe("skill-aware capability registry", () => {
const skillId = randomUUID();
const now = new Date().toISOString();
db.skills.upsertCompanySkill({
db.core.skills.upsertCompanySkill({
id: skillId,
companyId,
key: "frontend/react-ui",
@@ -92,9 +92,9 @@ describe("skill-aware capability registry", () => {
createdAt: now,
updatedAt: now,
});
db.skills.assignSkillToAgent(styledEngineerId, skillId);
db.core.skills.assignSkillToAgent(styledEngineerId, skillId);
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Build React dashboard widget",
description: "Create an accessible React component with hooks and Tailwind styling.",
@@ -103,7 +103,7 @@ describe("skill-aware capability registry", () => {
status: "todo",
});
const assignedId = db.tasks.autoAssignTask(taskId, companyId);
const assignedId = db.core.tasks.autoAssignTask(taskId, companyId);
expect(assignedId).toBe(styledEngineerId);
db.close();
@@ -114,7 +114,7 @@ describe("skill-aware capability registry", () => {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -122,12 +122,12 @@ describe("skill-aware capability registry", () => {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Registry Co",
description: "Tests capability registry prompt injection",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -135,7 +135,7 @@ describe("skill-aware capability registry", () => {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "CEO",
role: "CEO",
@@ -151,7 +151,7 @@ describe("skill-aware capability registry", () => {
const skillId = randomUUID();
const now = new Date().toISOString();
db.skills.upsertCompanySkill({
db.core.skills.upsertCompanySkill({
id: skillId,
companyId,
key: "frontend/react-ui",
@@ -169,9 +169,9 @@ describe("skill-aware capability registry", () => {
updatedAt: now,
});
const snapshot = db.snap.listSnapshot();
const snapshot = db.projection.snapshot.listSnapshot();
const prompt = buildTaskPrompt({
agent: db.entityCrud.getAgent(agentId),
agent: db.core.entity.getAgent(agentId),
apiUrl: "http://127.0.0.1:3210",
apiKey: "token",
runId: "run-1",
@@ -193,7 +193,7 @@ describe("skill-aware capability registry", () => {
allConnectors: snapshot.connectors
.filter((connector) => connector.id === "openai-codex")
.map((connector) => ({ id: connector.id, label: connector.label, status: connector.status, enabledModels: ["gpt-5.4"] })),
companySkillCatalog: db.skills.listCompanySkills(companyId).map((skill) => ({
companySkillCatalog: db.core.skills.listCompanySkills(companyId).map((skill) => ({
name: skill.name,
slug: skill.slug,
description: skill.description,
+17 -17
View File
@@ -28,7 +28,7 @@ function createNoopLogger() {
}
function createScaffold(db: AppDatabase) {
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -36,13 +36,13 @@ function createScaffold(db: AppDatabase) {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Thread Wait Co",
description: "Tests cofounder wait states and replies",
status: "active",
executionMode: "ai_cofounder",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: "/tmp/thread-wait",
@@ -50,7 +50,7 @@ function createScaffold(db: AppDatabase) {
repoRef: "",
isPrimary: true,
});
const ceoId = db.agents.saveAgent({
const ceoId = db.core.agents.saveAgent({
companyId,
name: "CEO",
role: "CEO",
@@ -63,7 +63,7 @@ function createScaffold(db: AppDatabase) {
capabilities: "Lead the company",
budgetMonthlyUsd: 250,
});
const engineerId = db.agents.saveAgent({
const engineerId = db.core.agents.saveAgent({
companyId,
name: "Engineer",
role: "Engineer",
@@ -76,7 +76,7 @@ function createScaffold(db: AppDatabase) {
capabilities: "Ship features",
budgetMonthlyUsd: 180,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Ship the feature",
description: "Implement the approved deliverable and wait for co-founder review.",
@@ -116,7 +116,7 @@ describe("thread wait + heartbeat integration", () => {
threadIntegration.onTaskCreated(taskId, companyId);
threadIntegration.onRunFinished("run-1", taskId, engineerId, companyId, "succeeded", null);
const thread = db.threads.listThreads({
const thread = db.core.threads.listThreads({
companyId,
type: "task",
relatedEntityType: "task",
@@ -128,12 +128,12 @@ describe("thread wait + heartbeat integration", () => {
throw new Error("Expected a task thread to exist for the completed run.");
}
let waitStates = db.threads.listThreadWaitStates(companyId).filter((entry) => entry.threadId === thread.id);
let waitStates = db.core.threads.listThreadWaitStates(companyId).filter((entry) => entry.threadId === thread.id);
expect(waitStates).toHaveLength(1);
expect(waitStates[0]?.waitingFor).toBe("user_reply");
expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(true);
const otherAgentId = db.agents.saveAgent({
const otherAgentId = db.core.agents.saveAgent({
companyId,
name: "Marketer",
role: "CMO",
@@ -141,7 +141,7 @@ describe("thread wait + heartbeat integration", () => {
status: "idle",
reportsTo: null,
connectorId: "openai-codex",
workspaceId: db.entityCrud.getTask(taskId).workspaceId ?? null,
workspaceId: db.core.entity.getTask(taskId).workspaceId ?? null,
model: null,
capabilities: "Drive marketing work",
budgetMonthlyUsd: 180,
@@ -165,7 +165,7 @@ describe("thread wait + heartbeat integration", () => {
body: "Board reviewed this deliverable. Continue.",
});
waitStates = db.threads.listThreadWaitStates(companyId).filter((entry) => entry.threadId === thread.id);
waitStates = db.core.threads.listThreadWaitStates(companyId).filter((entry) => entry.threadId === thread.id);
expect(waitStates).toHaveLength(0);
expect(threadIntegration.hasUnresolvedWaitStatesForAgent(companyId, engineerId)).toBe(false);
expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(false);
@@ -192,7 +192,7 @@ describe("thread wait + heartbeat integration", () => {
});
threadIntegration.onTaskCreated(taskId, companyId);
const thread = db.threads.listThreads({
const thread = db.core.threads.listThreads({
companyId,
type: "task",
relatedEntityType: "task",
@@ -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.approvalsMod.requestApproval({
const approvalId = db.core.approvals.requestApproval({
companyId,
relatedTaskId: taskId,
requestedByAgentId: engineerId,
@@ -215,7 +215,7 @@ describe("thread wait + heartbeat integration", () => {
});
threadIntegration.onApprovalCreated(approvalId, companyId, taskId, "draft_review", "Draft review needed");
let waitStates = db.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
let waitStates = db.core.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
expect(waitStates).toHaveLength(1);
expect(waitStates[0]?.waitingFor).toBe("user_approval");
expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(true);
@@ -234,17 +234,17 @@ describe("thread wait + heartbeat integration", () => {
body: "Board left a comment but did not decide approval yet.",
});
waitStates = db.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
waitStates = db.core.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
expect(waitStates).toHaveLength(1);
expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(true);
db.approvalsMod.decideApproval({
db.core.approvals.decideApproval({
approvalId,
state: "approved",
decisionNote: "Approved by board",
});
threadIntegration.onApprovalResolved(approvalId, companyId, "approved");
waitStates = db.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
waitStates = db.core.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
expect(waitStates).toHaveLength(0);
expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(false);
@@ -45,7 +45,7 @@ async function createHarness(): Promise<Harness> {
const db = new AppDatabase(profileDir);
db.init();
db.connectorsCrud.updateConnectorHealth({
db.core.connectors.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -53,12 +53,12 @@ async function createHarness(): Promise<Harness> {
lastError: null,
});
const companyId = db.company.saveCompany({
const companyId = db.core.company.saveCompany({
name: "Work Products Co",
description: "Tests archived visibility, bulk retirement, deliverable signal",
status: "active",
});
const workspaceId = db.workspacesMod.saveWorkspace({
const workspaceId = db.core.workspaces.saveWorkspace({
companyId,
name: "Primary",
localPath: workspacePath,
@@ -66,7 +66,7 @@ async function createHarness(): Promise<Harness> {
repoRef: "",
isPrimary: true,
});
const agentId = db.agents.saveAgent({
const agentId = db.core.agents.saveAgent({
companyId,
name: "Artifact Engineer",
role: "Engineer",
@@ -79,7 +79,7 @@ async function createHarness(): Promise<Harness> {
capabilities: "Writes files",
budgetMonthlyUsd: 100,
});
const taskId = db.tasks.saveTask({
const taskId = db.core.tasks.saveTask({
companyId,
title: "Produce artifact",
description: "",
@@ -88,7 +88,7 @@ async function createHarness(): Promise<Harness> {
priority: "medium",
status: "in_progress",
});
const run = db.runs.createRun({
const run = db.core.runs.createRun({
companyId,
taskId,
agentId,
@@ -107,7 +107,7 @@ async function createHarness(): Promise<Harness> {
}
function registerArtifact(harness: Harness, relativePath: string): string {
return harness.db.documentsMod.createWorkProduct({
return harness.db.core.documents.createWorkProduct({
companyId: harness.companyId,
taskId: harness.taskId,
workspaceId: harness.workspaceId,
@@ -126,12 +126,12 @@ describe("work_products archived visibility", () => {
try {
const activeId = registerArtifact(harness, "docs/active.md");
const archivedId = registerArtifact(harness, "docs/retired.md");
harness.db.documentsMod.updateWorkProduct(archivedId, harness.companyId, {
harness.db.core.documents.updateWorkProduct(archivedId, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
const snapshot = harness.db.snap.listSnapshot();
const snapshot = harness.db.projection.snapshot.listSnapshot();
const visibleIds = snapshot.workProducts.map((wp) => wp.id);
expect(visibleIds).toContain(activeId);
expect(visibleIds).not.toContain(archivedId);
@@ -145,12 +145,12 @@ describe("work_products archived visibility", () => {
try {
const activeId = registerArtifact(harness, "src/feature.ts");
const archivedId = registerArtifact(harness, "src/removed.ts");
harness.db.documentsMod.updateWorkProduct(archivedId, harness.companyId, {
harness.db.core.documents.updateWorkProduct(archivedId, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
const rows = harness.db.documentsMod.listWorkProductsForTask(harness.taskId, harness.companyId);
const rows = harness.db.core.documents.listWorkProductsForTask(harness.taskId, harness.companyId);
const ids = rows.map((r) => r.id);
expect(ids).toContain(activeId);
expect(ids).not.toContain(archivedId);
@@ -164,16 +164,16 @@ describe("work_products archived visibility", () => {
try {
const id = registerArtifact(harness, "notes/ghost.md");
expect(
harness.db.documentsMod.resolveWorkProductTarget(id, harness.companyId),
harness.db.core.documents.resolveWorkProductTarget(id, harness.companyId),
).not.toBeNull();
harness.db.documentsMod.updateWorkProduct(id, harness.companyId, {
harness.db.core.documents.updateWorkProduct(id, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
expect(
harness.db.documentsMod.resolveWorkProductTarget(id, harness.companyId),
harness.db.core.documents.resolveWorkProductTarget(id, harness.companyId),
).toMatchObject({ kind: "error", reason: "archived" });
} finally {
harness.db.close();
@@ -193,7 +193,7 @@ describe("work_products bulk retirement", () => {
ids.push(registerArtifact(harness, rel));
}
const archived = harness.db.documentsMod.archiveWorkProductsByExternalPaths({
const archived = harness.db.core.documents.archiveWorkProductsByExternalPaths({
companyId: harness.companyId,
workspaceId: harness.workspaceId,
provider: "filesystem",
@@ -206,7 +206,7 @@ describe("work_products bulk retirement", () => {
for (const id of ids) {
expect(archivedIdSet.has(id)).toBe(true);
}
const visible = harness.db.snap.listSnapshot().workProducts;
const visible = harness.db.projection.snapshot.listSnapshot().workProducts;
expect(visible.length).toBe(0);
} finally {
harness.db.close();
@@ -217,7 +217,7 @@ describe("work_products bulk retirement", () => {
const harness = await createHarness();
try {
const id = registerArtifact(harness, "tmp/scratch.log");
harness.db.documentsMod.archiveWorkProductsByExternalPaths({
harness.db.core.documents.archiveWorkProductsByExternalPaths({
companyId: harness.companyId,
workspaceId: harness.workspaceId,
provider: "filesystem",
@@ -225,7 +225,7 @@ describe("work_products bulk retirement", () => {
lastTouchedByRunId: harness.runId,
});
const second = harness.db.documentsMod.archiveWorkProductsByExternalPaths({
const second = harness.db.core.documents.archiveWorkProductsByExternalPaths({
companyId: harness.companyId,
workspaceId: harness.workspaceId,
provider: "filesystem",
@@ -235,7 +235,7 @@ describe("work_products bulk retirement", () => {
expect(second).toHaveLength(0);
expect(
harness.db.documentsMod.resolveWorkProductTarget(id, harness.companyId),
harness.db.core.documents.resolveWorkProductTarget(id, harness.companyId),
).toMatchObject({ kind: "error", reason: "archived" });
} finally {
harness.db.close();
@@ -252,7 +252,7 @@ describe("work_products bulk retirement", () => {
const workProductId = registerArtifact(harness, relPath);
expect(
harness.db.documentsMod.resolveWorkProductTarget(workProductId, harness.companyId),
harness.db.core.documents.resolveWorkProductTarget(workProductId, harness.companyId),
).not.toBeNull();
const baseline = {
@@ -277,7 +277,7 @@ describe("work_products bulk retirement", () => {
expect(retired.map((o) => (o as { relativePath: string }).relativePath)).toContain(relPath);
expect(
harness.db.documentsMod.resolveWorkProductTarget(workProductId, harness.companyId),
harness.db.core.documents.resolveWorkProductTarget(workProductId, harness.companyId),
).toMatchObject({ kind: "error", reason: "archived" });
} finally {
harness.db.close();
@@ -290,19 +290,19 @@ describe("work_products deliverable signal", () => {
const harness = await createHarness();
try {
const id = registerArtifact(harness, "deliverables/final.md");
const beforeArchive = harness.db.knowledgeMod.collectRunDeliverableSignals(
const beforeArchive = harness.db.core.knowledge.collectRunDeliverableSignals(
harness.runId,
harness.companyId,
harness.taskId,
);
expect(beforeArchive.hasWorkProduct).toBe(true);
harness.db.documentsMod.updateWorkProduct(id, harness.companyId, {
harness.db.core.documents.updateWorkProduct(id, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
const afterArchive = harness.db.knowledgeMod.collectRunDeliverableSignals(
const afterArchive = harness.db.core.knowledge.collectRunDeliverableSignals(
harness.runId,
harness.companyId,
harness.taskId,