Remove final AppDatabase pass-through methods with ESLint guard (C1 part 3/3)

Migrate all remaining pass-through call sites (social, skills, budget,
entityCrud, documents, knowledge, automation, wakeup, backup, threads,
settings, snapshot, connectors, workspaces, activity) to their owning
domain modules. `AppDatabase` now carries only three methods:

  - createHireRequest (multi-module composite: agents + approvalsMod)
  - rollbackConfigRevision (multi-module composite: documents + entityCrud)
  - queryAll (raw-SQL escape hatch, @internal)

The vault/env-binding infrastructure previously passed argument-by-
argument into `entityCrud.saveSecret`/`resolveSecretEnv` now binds at
module construction, letting callers invoke `db.entityCrud.saveSecret({...})`
without carrying vault plumbing.

Structural types that narrowed AppDatabase to a bag of flat methods
(`ConnectorModelPolicyDeps` callers, `CapabilityMatchDb`, test mocks in
budget-enforcement / budget-incidents / task-quality-gates /
failure-escalation / task-quality-gates-sweep) are reshaped to the new
namespace. `connectorPolicyDepsFromDb` replaces the old pattern of
handing the whole AppDatabase to `validateConnectorModelSelection`.

A new ESLint rule in eslint.config.mjs blocks new top-level methods on
AppDatabase so the pass-through layer cannot silently grow back.
`AppDatabase.ts` dropped from 193 lines to 58; `AppDatabaseBase` lost
the 270-line trailing pass-through block.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 13:31:39 -04:00
1 parent a69fbb053b
commit 118e3d8795
120 files changed
+838 -933

No files matched your search

@@ -70,7 +70,7 @@ describe("agent model switching", () => {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -83,7 +83,7 @@ describe("agent model switching", () => {
description: "Tests post-hire model switching",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -24,7 +24,7 @@ async function createHarness() {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -37,7 +37,7 @@ async function createHarness() {
description: "Tests manager-driven recursive hires",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
+1 -1
View File
@@ -25,7 +25,7 @@ async function createHarness() {
db.init();
const companyId = db.company.saveCompany({ name: "Orbit Foundry", description: "API test", status: "active" });
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -11,7 +11,7 @@ const { createAgent } = shared;
describe("Automation Rules CRUD", () => {
it("creates, reads, toggles, and deletes an automation rule", () => {
const ruleId = shared.db.saveAutomationRule({
const ruleId = shared.db.automationMod.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.listSnapshot();
const snapshot = shared.db.snap.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.toggleAutomationRule(ruleId, shared.companyId, "paused");
const updated = shared.db.listSnapshot().automationRules.find(r => r.id === ruleId);
shared.db.automationMod.toggleAutomationRule(ruleId, shared.companyId, "paused");
const updated = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(updated!.status).toBe("paused");
// Record execution
shared.db.recordAutomationExecution(ruleId, shared.companyId, "Auto-escalate blocked tasks", "task_blocked", "escalate_to_manager", "Escalated task-123");
const afterExec = shared.db.listSnapshot().automationRules.find(r => r.id === ruleId);
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);
expect(afterExec!.executionCount).toBe(1);
expect(afterExec!.lastExecutedAt).toBeTruthy();
// Automation log
const log = shared.db.getAutomationLog(shared.companyId);
const log = shared.db.automationMod.getAutomationLog(shared.companyId);
expect(log).toHaveLength(1);
expect(log[0].ruleName).toBe("Auto-escalate blocked tasks");
// Delete
shared.db.deleteAutomationRule(ruleId, shared.companyId);
const afterDelete = shared.db.listSnapshot().automationRules.find(r => r.id === ruleId);
shared.db.automationMod.deleteAutomationRule(ruleId, shared.companyId);
const afterDelete = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(afterDelete).toBeUndefined();
});
it("updates an existing rule", () => {
const ruleId = shared.db.saveAutomationRule({
const ruleId = shared.db.automationMod.saveAutomationRule({
companyId: shared.companyId,
name: "Original name",
trigger: "task_created",
action: "assign_task",
});
shared.db.saveAutomationRule({
shared.db.automationMod.saveAutomationRule({
id: ruleId,
companyId: shared.companyId,
name: "Updated name",
@@ -77,7 +77,7 @@ describe("Automation Rules CRUD", () => {
priority: 90,
});
const rule = shared.db.listSnapshot().automationRules.find(r => r.id === ruleId);
const rule = shared.db.snap.listSnapshot().automationRules.find(r => r.id === ruleId);
expect(rule!.name).toBe("Updated name");
expect(rule!.action).toBe("notify_agent");
expect(rule!.priority).toBe(90);
@@ -171,7 +171,7 @@ 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.saveProject({
const projectId = shared.db.entityCrud.saveProject({
companyId: shared.companyId,
name: "Cross-team Project",
description: "Scope",
@@ -229,7 +229,7 @@ describe("Agent Messages", () => {
it("appears in snapshot", () => {
shared.db.messages.sendAgentMessage({ companyId: shared.companyId, fromAgentId: agentAId, channel: "company", subject: "Snapshot test", body: "Hi" });
const snapshot = shared.db.listSnapshot();
const snapshot = shared.db.snap.listSnapshot();
expect(snapshot.agentMessages.length).toBeGreaterThanOrEqual(1);
expect(snapshot.agentMessages[0].subject).toBe("Snapshot test");
});
@@ -316,7 +316,7 @@ describe("Auto Task Assignment", () => {
describe("Workflow Pipelines", () => {
it("creates, activates, and deletes a workflow", () => {
const wfId = shared.db.saveWorkflow({
const wfId = shared.db.automationMod.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.listSnapshot();
const snapshot = shared.db.snap.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.deleteWorkflow(wfId, shared.companyId);
expect(shared.db.listSnapshot().workflows.find(w => w.id === wfId)).toBeUndefined();
shared.db.automationMod.deleteWorkflow(wfId, shared.companyId);
expect(shared.db.snap.listSnapshot().workflows.find(w => w.id === wfId)).toBeUndefined();
});
});
@@ -34,7 +34,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
shared.db.runs.markRunStatus(run.id, "running", "Started");
// Verify it's running
let snapshot = shared.db.listSnapshot();
let snapshot = shared.db.snap.listSnapshot();
expect(snapshot.runs.find((r) => r.id === run.id)?.status).toBe("running");
// Simulate app restart — close and re-init
@@ -44,7 +44,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
shared.db = new AppDatabase(profileDir);
shared.db.init(); // This calls interruptStaleRuns()
snapshot = shared.db.listSnapshot();
snapshot = shared.db.snap.listSnapshot();
const recoveredRun = snapshot.runs.find((r) => r.id === run.id);
expect(recoveredRun?.status).toBe("interrupted");
});
@@ -83,7 +83,7 @@ describe("Step 7: Worker crash recovery (database layer)", () => {
unattributedCost: true,
});
const snapshot = shared.db.listSnapshot();
const snapshot = shared.db.snap.listSnapshot();
const recovered = snapshot.runs.find((r) => r.id === run.id);
expect(recovered?.status).toBe("interrupted");
expect(recovered?.errorMessage).toBe("Worker process exited unexpectedly.");
@@ -111,7 +111,7 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
expect(ctoChain[0].id).toBe(ceoId);
// 8. Create task tree
const projectId = shared.db.saveProject({
const projectId = shared.db.entityCrud.saveProject({
companyId: shared.companyId,
name: "Launch MVP",
description: "Build and launch MVP",
@@ -150,8 +150,8 @@ describe("E2E: Full autonomous CEO cold start flow", () => {
expect(subtask.parentId).toBe(parentTaskId);
// 9. Wakeup request test: enqueue wake while IC is busy
shared.db.enqueueWakeupRequest(shared.companyId, icId, "comment", "comment");
const queuedWakes = shared.db.listWakeupRequests(shared.companyId, { agentId: icId, status: "queued" });
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, icId, "comment", "comment");
const queuedWakes = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId: icId, status: "queued" });
expect(queuedWakes).toHaveLength(1);
expect(queuedWakes[0].source).toBe("comment");
@@ -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.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
shared.db.enqueueWakeupRequest(shared.companyId, agentId, "report_blocked", "report_blocked");
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");
// Verify coalesced into single row with all triggers
const wakes = shared.db.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
const wakes = shared.db.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.listWakeupRequests(shared.companyId, { agentId, status: "queued" })).toHaveLength(1);
expect(shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId, status: "queued" })).toHaveLength(1);
});
});
@@ -45,7 +45,7 @@ describe("Step 6: Run failure escalation (database layer)", () => {
expect(outcome.budgetHardStopped).toBe(false);
const snapshot = shared.db.listSnapshot();
const snapshot = shared.db.snap.listSnapshot();
const finishedRun = snapshot.runs.find((r) => r.id === run.id);
expect(finishedRun?.status).toBe("failed");
expect(finishedRun?.errorMessage).toBe("Process crashed");
@@ -60,7 +60,7 @@ export function installSharedSetup(): SharedHandle {
status: "active",
});
state.workspaceId = state.db.saveWorkspace({
state.workspaceId = state.db.workspacesMod.saveWorkspace({
companyId: state.companyId,
name: "Primary",
localPath: profileDir,
@@ -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.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "subtask_completed", "subtask_completed");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agentId, "comment", "comment");
// List returns the coalesced wake
const wakes = shared.db.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
const wakes = shared.db.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.listWakeupRequests(shared.companyId, { agentId, status: "queued" });
const wakes = shared.db.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.enqueueWakeupRequest(shared.companyId, agent1, "comment", "comment");
shared.db.enqueueWakeupRequest(shared.companyId, agent2, "subtask_completed", "subtask_completed");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agent1, "comment", "comment");
shared.db.wakeup.enqueueWakeupRequest(shared.companyId, agent2, "subtask_completed", "subtask_completed");
const wakes1 = shared.db.listWakeupRequests(shared.companyId, { agentId: agent1, status: "queued" });
const wakes1 = shared.db.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.listWakeupRequests(shared.companyId, { agentId: agent2, status: "queued" });
const wakes2 = shared.db.wakeup.listWakeupRequests(shared.companyId, { agentId: agent2, status: "queued" });
expect(wakes2).toHaveLength(1);
expect(wakes2[0].source).toBe("subtask_completed");
});
@@ -69,7 +69,7 @@ describe("connector model enforcement", () => {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -82,7 +82,7 @@ describe("connector model enforcement", () => {
description: "Blocks runs when agent models are disabled",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -113,7 +113,7 @@ describe("connector model enforcement", () => {
status: "todo",
});
db.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
db.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.listSnapshot().runs).toHaveLength(0);
expect(db.snap.listSnapshot().runs).toHaveLength(0);
db.close();
});
@@ -133,7 +133,7 @@ describe("connector model enforcement", () => {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -146,7 +146,7 @@ describe("connector model enforcement", () => {
description: "Rejects invalid queued runs during recovery",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -187,12 +187,12 @@ describe("connector model enforcement", () => {
const checkoutSuccess = db.tasks.checkoutTask(taskId, run.id);
expect(checkoutSuccess).toBe(true);
db.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
db.settings.setDisabledModels(companyId, "openai-codex", [{ id: "gpt-5.4", label: "gpt-5.4" }]);
const { taskRunner } = createOrchestrationHarness(db);
taskRunner.resumeQueuedRuns();
const recoveredRun = db.listSnapshot().runs.find((entry) => entry.id === run.id);
const recoveredRun = db.snap.listSnapshot().runs.find((entry) => entry.id === run.id);
expect(recoveredRun?.status).toBe("failed");
expect(recoveredRun?.errorMessage).toContain("Connector model is disabled or invalid");
+5 -5
View File
@@ -57,7 +57,7 @@ const mockLogger = {
function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
const connectorId: ConnectorId = "gemini-cli";
db.saveConnector({
db.connectorsCrud.saveConnector({
id: connectorId,
model: "gemini-2.5-pro",
envBindingText: "",
@@ -70,7 +70,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary Workspace",
localPath: "/tmp/pipeline-test",
@@ -93,7 +93,7 @@ function scaffold(db: AppDatabase, budgetAmountCents = 500): ScaffoldResult {
budgetMonthlyUsd: 100,
});
const goalId = db.saveGoal({
const goalId = db.entityCrud.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.saveProject({
const projectId = db.entityCrud.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.saveBudgetPolicy({
const policyId = db.budget.saveBudgetPolicy({
companyId,
scopeType: "company",
scopeId: companyId,
+15 -15
View File
@@ -43,7 +43,7 @@ describe("AppDatabase", () => {
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -66,7 +66,7 @@ describe("AppDatabase", () => {
budgetMonthlyUsd: 200,
});
const goalId = db.saveGoal({
const goalId = db.entityCrud.saveGoal({
companyId,
title: "Ship the desktop app",
description: "Reach packaged desktop parity.",
@@ -74,7 +74,7 @@ describe("AppDatabase", () => {
status: "active",
});
const projectId = db.saveProject({
const projectId = db.entityCrud.saveProject({
companyId,
goalId,
name: "Desktop rebuild",
@@ -95,21 +95,21 @@ describe("AppDatabase", () => {
status: "todo",
});
db.saveSecret({
db.entityCrud.saveSecret({
companyId,
name: "vault-openai",
description: "Test key",
value: "sk-test-123",
});
db.saveConnector({
db.connectorsCrud.saveConnector({
id: "openai-codex",
model: null,
envBindingText: "OPENAI_API_KEY=vault-openai",
notes: "Connector note",
});
expect(db.resolveSecretEnv("OPENAI_API_KEY=vault-openai", companyId)).toEqual({
expect(db.entityCrud.resolveSecretEnv("OPENAI_API_KEY=vault-openai", companyId)).toEqual({
OPENAI_API_KEY: "sk-test-123",
});
@@ -136,22 +136,22 @@ describe("AppDatabase", () => {
unattributedCost: false,
});
const snapshotBeforeBackup = db.listSnapshot();
const snapshotBeforeBackup = db.snap.listSnapshot();
expect(snapshotBeforeBackup.companies).toHaveLength(1);
expect(snapshotBeforeBackup.runs[0]?.status).toBe("succeeded");
expect(snapshotBeforeBackup.tasks[0]?.activeRunId).toBeNull();
await db.exportBackup(backupDir);
await db.backupMod.exportBackup(backupDir);
db.company.saveCompany({
name: "Temporary company",
description: "Should disappear after restore",
status: "active",
});
expect(db.listSnapshot().companies).toHaveLength(2);
expect(db.snap.listSnapshot().companies).toHaveLength(2);
await db.restoreFromBackup(backupDir);
const restoredSnapshot = db.listSnapshot();
await db.backupMod.restoreFromBackup(backupDir);
const restoredSnapshot = db.snap.listSnapshot();
expect(restoredSnapshot.companies).toHaveLength(1);
expect(restoredSnapshot.companies[0]?.name).toBe("Orbit Foundry");
expect(restoredSnapshot.runs[0]?.summary).toBe("Completed successfully");
@@ -176,7 +176,7 @@ describe("AppDatabase", () => {
status: "active",
});
const alphaWorkspaceId = db.saveWorkspace({
const alphaWorkspaceId = db.workspacesMod.saveWorkspace({
companyId: alphaCompanyId,
name: "Alpha Workspace",
localPath: profileDir,
@@ -185,7 +185,7 @@ describe("AppDatabase", () => {
isPrimary: true,
});
const betaWorkspaceId = db.saveWorkspace({
const betaWorkspaceId = db.workspacesMod.saveWorkspace({
companyId: betaCompanyId,
name: "Beta Workspace",
localPath: profileDir,
@@ -242,9 +242,9 @@ describe("AppDatabase", () => {
status: "todo",
});
db.setCurrentCompany(alphaCompanyId);
db.settings.setCurrentCompany(alphaCompanyId);
const rendererSnapshot = db.listRendererSnapshot();
const rendererSnapshot = db.snap.listRendererSnapshot();
expect(rendererSnapshot.currentCompanyId).toBe(alphaCompanyId);
expect(rendererSnapshot.companies).toHaveLength(2);
expect(rendererSnapshot.connectors.length).toBeGreaterThan(0);
@@ -26,7 +26,7 @@ async function createHarness() {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -39,7 +39,7 @@ async function createHarness() {
description: "Tests document revision provenance through run completion",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -71,7 +71,7 @@ async function createHarness() {
});
db.tasks.setTaskType(taskId, "research");
const existingDocumentId = db.saveDocument({
const existingDocumentId = db.documentsMod.saveDocument({
companyId,
type: "knowledge_article",
title: "Market report",
@@ -149,7 +149,7 @@ describe("document run provenance", () => {
)[0];
expect(updatedDocument?.sourceRunId).toBe(harness.run.id);
const persistedRun = harness.db.listSnapshot().runs.find((entry) => entry.id === harness.run.id);
const persistedRun = harness.db.snap.listSnapshot().runs.find((entry) => entry.id === harness.run.id);
if (!persistedRun) {
throw new Error("Expected persisted run record for provenance test.");
}
@@ -307,7 +307,7 @@ describe("document run provenance", () => {
);
expect(createResponse.status).toBe(201);
const approvals = harness.db.listSnapshot().approvals.filter((approval) => approval.type === "deliverable_review");
const approvals = harness.db.snap.listSnapshot().approvals.filter((approval) => approval.type === "deliverable_review");
expect(approvals).toHaveLength(1);
expect(approvals[0]?.relatedTaskId).toBe(harness.taskId);
} finally {
+11 -11
View File
@@ -54,9 +54,9 @@ function buildKickoffPayload(db: AppDatabase, summary: { companyId: string; lead
const agent = db.entityCrud.getAgent(summary.leadAgentId);
const task = db.entityCrud.getTask(summary.taskId);
const connector = db.getConnector(agent.connectorId);
const workspace = summary.workspaceId ? db.getWorkspace(summary.workspaceId) : null;
const company = db.listSnapshot().companies.find((entry) => entry.id === summary.companyId);
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);
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.listSnapshot(),
snapshot: db.snap.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.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -128,8 +128,8 @@ describe("onboarding model pool integration", () => {
const agent = db.entityCrud.getAgent(summary.leadAgentId);
expect(agent.connectorId).toBe("openai-codex");
expect(agent.model).toBe(enabledModel);
expect(db.getDisabledModels(summary.companyId, "openai-codex")).toEqual([{ id: disabledModel, label: disabledModel }]);
expect(db.getCurrentCompanyId()).toBe(summary.companyId);
expect(db.settings.getDisabledModels(summary.companyId, "openai-codex")).toEqual([{ id: disabledModel, label: disabledModel }]);
expect(db.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.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "anthropic",
status: "ready",
authState: "authenticated",
@@ -205,7 +205,7 @@ describe("onboarding model pool integration", () => {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -254,7 +254,7 @@ describe("onboarding model pool integration", () => {
throw new Error("openai-codex requires a default and fallback model for reroute testing.");
}
db.updateConnectorHealth({
db.connectorsCrud.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.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
+1 -1
View File
@@ -106,7 +106,7 @@ describe("pi-mono migrations 27 + 28", () => {
const db = new AppDatabase(dir);
db.init();
const rows = db.listSnapshot().connectors.map((entry) => entry.id);
const rows = db.snap.listSnapshot().connectors.map((entry) => entry.id);
expect(rows.length).toBe(26);
expect(rows).toContain("claude-pro");
expect(rows).toContain("amazon-bedrock");
+6 -6
View File
@@ -54,7 +54,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
const connectorId: ConnectorId = "gemini-cli";
// Connector
db.saveConnector({
db.connectorsCrud.saveConnector({
id: connectorId,
model: "gemini-2.5-pro",
envBindingText: "",
@@ -69,7 +69,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
});
// Workspace
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary Workspace",
localPath: "/tmp/recovery-test",
@@ -94,7 +94,7 @@ function scaffold(db: AppDatabase): ScaffoldResult {
});
// Goal
const goalId = db.saveGoal({
const goalId = db.entityCrud.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.saveProject({
const projectId = db.entityCrud.saveProject({
companyId,
goalId,
name: "Auth Module",
@@ -169,7 +169,7 @@ function createAndStartRun(
db.runs.markRunStatus(runId, "running", "Starting execution");
if (opts.claimWorkspace !== false) {
db.claimWorkspaceLock(opts.workspaceId, runId);
db.workspacesMod.claimWorkspaceLock(opts.workspaceId, runId);
}
// Set agent status to "running" to simulate active execution
@@ -385,7 +385,7 @@ describe("Process Recovery -- Worker Crash Detection", () => {
workspaceId: s.workspaceId,
connectorId: s.connectorId,
});
expect(db.claimWorkspaceLock(s.workspaceId, newRunId)).toBe(true);
expect(db.workspacesMod.claimWorkspaceLock(s.workspaceId, newRunId)).toBe(true);
});
it("tasks set to blocked after crash", () => {
@@ -24,7 +24,7 @@ describe("skill-aware capability registry", () => {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -37,7 +37,7 @@ describe("skill-aware capability registry", () => {
description: "Tests skill-aware assignment",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -75,7 +75,7 @@ describe("skill-aware capability registry", () => {
const skillId = randomUUID();
const now = new Date().toISOString();
db.upsertCompanySkill({
db.skills.upsertCompanySkill({
id: skillId,
companyId,
key: "frontend/react-ui",
@@ -92,7 +92,7 @@ describe("skill-aware capability registry", () => {
createdAt: now,
updatedAt: now,
});
db.assignSkillToAgent(styledEngineerId, skillId);
db.skills.assignSkillToAgent(styledEngineerId, skillId);
const taskId = db.tasks.saveTask({
companyId,
@@ -114,7 +114,7 @@ describe("skill-aware capability registry", () => {
const db = new AppDatabase(profileDir);
db.init();
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -127,7 +127,7 @@ describe("skill-aware capability registry", () => {
description: "Tests capability registry prompt injection",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: profileDir,
@@ -151,7 +151,7 @@ describe("skill-aware capability registry", () => {
const skillId = randomUUID();
const now = new Date().toISOString();
db.upsertCompanySkill({
db.skills.upsertCompanySkill({
id: skillId,
companyId,
key: "frontend/react-ui",
@@ -169,7 +169,7 @@ describe("skill-aware capability registry", () => {
updatedAt: now,
});
const snapshot = db.listSnapshot();
const snapshot = db.snap.listSnapshot();
const prompt = buildTaskPrompt({
agent: db.entityCrud.getAgent(agentId),
apiUrl: "http://127.0.0.1:3210",
@@ -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.listCompanySkills(companyId).map((skill) => ({
companySkillCatalog: db.skills.listCompanySkills(companyId).map((skill) => ({
name: skill.name,
slug: skill.slug,
description: skill.description,
@@ -28,7 +28,7 @@ function createNoopLogger() {
}
function createScaffold(db: AppDatabase) {
db.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -42,7 +42,7 @@ function createScaffold(db: AppDatabase) {
status: "active",
executionMode: "ai_cofounder",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: "/tmp/thread-wait",
@@ -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.listThreads({
const thread = db.threads.listThreads({
companyId,
type: "task",
relatedEntityType: "task",
@@ -128,7 +128,7 @@ describe("thread wait + heartbeat integration", () => {
throw new Error("Expected a task thread to exist for the completed run.");
}
let waitStates = db.listThreadWaitStates(companyId).filter((entry) => entry.threadId === thread.id);
let waitStates = db.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);
@@ -165,7 +165,7 @@ describe("thread wait + heartbeat integration", () => {
body: "Board reviewed this deliverable. Continue.",
});
waitStates = db.listThreadWaitStates(companyId).filter((entry) => entry.threadId === thread.id);
waitStates = db.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.listThreads({
const thread = db.threads.listThreads({
companyId,
type: "task",
relatedEntityType: "task",
@@ -215,7 +215,7 @@ describe("thread wait + heartbeat integration", () => {
});
threadIntegration.onApprovalCreated(approvalId, companyId, taskId, "draft_review", "Draft review needed");
let waitStates = db.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
let waitStates = db.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,7 +234,7 @@ describe("thread wait + heartbeat integration", () => {
body: "Board left a comment but did not decide approval yet.",
});
waitStates = db.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
waitStates = db.threads.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
expect(waitStates).toHaveLength(1);
expect(checkpointEngine.shouldPauseHeartbeat(companyId, engineerId)).toBe(true);
@@ -244,7 +244,7 @@ describe("thread wait + heartbeat integration", () => {
decisionNote: "Approved by board",
});
threadIntegration.onApprovalResolved(approvalId, companyId, "approved");
waitStates = db.listThreadWaitStates(companyId).filter((entry) => entry.relatedApprovalId === approvalId);
waitStates = db.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.updateConnectorHealth({
db.connectorsCrud.updateConnectorHealth({
id: "openai-codex",
status: "ready",
authState: "authenticated",
@@ -58,7 +58,7 @@ async function createHarness(): Promise<Harness> {
description: "Tests archived visibility, bulk retirement, deliverable signal",
status: "active",
});
const workspaceId = db.saveWorkspace({
const workspaceId = db.workspacesMod.saveWorkspace({
companyId,
name: "Primary",
localPath: workspacePath,
@@ -107,7 +107,7 @@ async function createHarness(): Promise<Harness> {
}
function registerArtifact(harness: Harness, relativePath: string): string {
return harness.db.createWorkProduct({
return harness.db.documentsMod.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.updateWorkProduct(archivedId, harness.companyId, {
harness.db.documentsMod.updateWorkProduct(archivedId, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
const snapshot = harness.db.listSnapshot();
const snapshot = harness.db.snap.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.updateWorkProduct(archivedId, harness.companyId, {
harness.db.documentsMod.updateWorkProduct(archivedId, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
const rows = harness.db.listWorkProductsForTask(harness.taskId, harness.companyId);
const rows = harness.db.documentsMod.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.resolveWorkProductTarget(id, harness.companyId),
harness.db.documentsMod.resolveWorkProductTarget(id, harness.companyId),
).not.toBeNull();
harness.db.updateWorkProduct(id, harness.companyId, {
harness.db.documentsMod.updateWorkProduct(id, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
expect(
harness.db.resolveWorkProductTarget(id, harness.companyId),
harness.db.documentsMod.resolveWorkProductTarget(id, harness.companyId),
).toBeNull();
} finally {
harness.db.close();
@@ -193,7 +193,7 @@ describe("work_products bulk retirement", () => {
ids.push(registerArtifact(harness, rel));
}
const archived = harness.db.archiveWorkProductsByExternalPaths({
const archived = harness.db.documentsMod.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.listSnapshot().workProducts;
const visible = harness.db.snap.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.archiveWorkProductsByExternalPaths({
harness.db.documentsMod.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.archiveWorkProductsByExternalPaths({
const second = harness.db.documentsMod.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.resolveWorkProductTarget(id, harness.companyId),
harness.db.documentsMod.resolveWorkProductTarget(id, harness.companyId),
).toBeNull();
} finally {
harness.db.close();
@@ -252,7 +252,7 @@ describe("work_products bulk retirement", () => {
const workProductId = registerArtifact(harness, relPath);
expect(
harness.db.resolveWorkProductTarget(workProductId, harness.companyId),
harness.db.documentsMod.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.resolveWorkProductTarget(workProductId, harness.companyId),
harness.db.documentsMod.resolveWorkProductTarget(workProductId, harness.companyId),
).toBeNull();
} 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.collectRunDeliverableSignals(
const beforeArchive = harness.db.knowledgeMod.collectRunDeliverableSignals(
harness.runId,
harness.companyId,
harness.taskId,
);
expect(beforeArchive.hasWorkProduct).toBe(true);
harness.db.updateWorkProduct(id, harness.companyId, {
harness.db.documentsMod.updateWorkProduct(id, harness.companyId, {
status: "archived",
lastTouchedByRunId: harness.runId,
});
const afterArchive = harness.db.collectRunDeliverableSignals(
const afterArchive = harness.db.knowledgeMod.collectRunDeliverableSignals(
harness.runId,
harness.companyId,
harness.taskId,