Codemod db pass-through calls to domain modules: tasks + agents (C1 part 1/3)

Rewrite ~525 call sites from `db.<method>()` to `db.<module>.<method>()`
for tasks and agents domains (including `getAgent`/`findAgent`/`getTask`
which live on the `entityCrud` field). Delete the corresponding
pass-through methods on AppDatabaseBase. Structural types that narrowed
`db` to a bag of flat methods (CapabilityMatchDb, EscalationDeps,
SweepStaleReviewsDeps) are reshaped to match the new namespace. Internal
callback references inside database.ts/database-base.ts now invoke the
owning module directly (e.g. `this.agents.saveAgent`) rather than the
deleted pass-through.

The codemod lives at scripts/codemod/remove-appdatabase-passthrough.mjs
and filters by owning module + optional explicit method list. It is
idempotent and does not re-rewrite already-namespaced calls.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 13:17:01 -04:00
1 parent 411294afa6
commit 5e9b7acbc6
95 files changed
+1123 -793

No files matched your search

+4 -4
View File
@@ -48,12 +48,12 @@ export function handleWorkerExit(
}
// EXEC-02: Release execution lock on crash recovery
if (run.taskId) {
db.releaseTaskLock(run.taskId, run.id);
db.tasks.releaseTaskLock(run.taskId, run.id);
}
affectedAgentIds.add(run.agentId);
affectedCompanyIds.set(run.agentId, run.companyId);
const chain = db.getChainOfCommand(run.agentId);
const chain = db.agents.getChainOfCommand(run.agentId);
if (chain.length > 0) {
wakeAgentIfPossible(chain[0].id, run.companyId, "report_failed");
}
@@ -98,8 +98,8 @@ export function handleWorkerExit(
if (candidate.workspaceId) {
db.releaseWorkspaceLock(candidate.workspaceId, candidate.id);
}
const task = candidate.taskId ? db.getTask(candidate.taskId) : null;
const agent = db.getAgent(candidate.agentId);
const task = candidate.taskId ? db.entityCrud.getTask(candidate.taskId) : null;
const agent = db.entityCrud.getAgent(candidate.agentId);
const connector = db.getConnector(agent.connectorId);
const { workspace, lockMode } = resolveWorkspaceWithLockMode(db, task, agent, candidate.companyId);
const recoveryCompany = recoverySnapshot.companies.find((company) => company.id === candidate.companyId);
+2 -2
View File
@@ -85,8 +85,8 @@ export interface WorkerServiceDependencies {
dispatchRunToWorker: (params: {
runId: string;
companyId: string;
agent: ReturnType<AppDatabase["getAgent"]>;
task: ReturnType<AppDatabase["getTask"]> | null;
agent: ReturnType<AppDatabase["entityCrud"]["getAgent"]>;
task: ReturnType<AppDatabase["entityCrud"]["getTask"]> | null;
connector: ReturnType<AppDatabase["getConnector"]>;
workspace: ReturnType<AppDatabase["getWorkspace"]>;
workspaceMode: "exclusive" | "shared" | "none";
@@ -7,7 +7,7 @@ import type { HandlerContext, HandlerDeps, WorkerMessageEvent } from "./handler-
type RunFinishedEvent = Extract<WorkerMessageEvent, { type: "run-finished" }>;
type RunRecord = ReturnType<HandlerDeps["db"]["getRun"]>;
type TaskRecord = ReturnType<HandlerDeps["db"]["getTask"]>;
type TaskRecord = ReturnType<HandlerDeps["db"]["entityCrud"]["getTask"]>;
export interface RunFinishedContext {
run: RunRecord;
@@ -56,7 +56,7 @@ export function finalizeRun(
let task: TaskRecord | null = null;
if (run.taskId) {
try {
task = db.getTask(run.taskId);
task = db.entityCrud.getTask(run.taskId);
} catch (error) {
logger.warn(
`[finalizeRun] getTask(${run.taskId}) failed; task may have been deleted: ${error instanceof Error ? error.message : String(error)}`,
@@ -97,9 +97,9 @@ export function accumulateAndRotateSession(
// heartbeat run — the exact failure mode that lets a taskless transcript
// grow past the model's context window. Resolve the session through the
// agent, never through the task.
let agentRecord: ReturnType<HandlerDeps["db"]["getAgent"]>;
let agentRecord: ReturnType<HandlerDeps["db"]["entityCrud"]["getAgent"]>;
try {
agentRecord = db.getAgent(run.agentId);
agentRecord = db.entityCrud.getAgent(run.agentId);
} catch (error) {
logger.warn(
`[session] accumulateAndRotateSession: getAgent(${run.agentId}) failed; skipping: ${error instanceof Error ? error.message : String(error)}`,
@@ -107,7 +107,7 @@ export function accumulateAndRotateSession(
return;
}
if (!agentRecord.sessionId) return;
const session = db.getSessionById(agentRecord.sessionId);
const session = db.tasks.getSessionById(agentRecord.sessionId);
if (!session) return;
sessionService.accumulateTokenUsage(
@@ -120,7 +120,7 @@ export function accumulateAndRotateSession(
// that include this run, otherwise a run that just crossed the
// threshold waits a full additional cycle to rotate — the exact
// failure mode that let transcripts balloon past the context window.
const updatedSession = db.getSessionById(agentRecord.sessionId);
const updatedSession = db.tasks.getSessionById(agentRecord.sessionId);
if (!updatedSession) return;
const rotationResult = sessionService.evaluateRotation(updatedSession);
if (rotationResult.shouldRotate) {
@@ -154,9 +154,9 @@ export function emitAndNotifyCompletion(
});
}
let updatedAgent: ReturnType<HandlerDeps["db"]["getAgent"]> | null = null;
let updatedAgent: ReturnType<HandlerDeps["db"]["entityCrud"]["getAgent"]> | null = null;
try {
updatedAgent = db.getAgent(run.agentId);
updatedAgent = db.entityCrud.getAgent(run.agentId);
} catch (error) {
logger.warn(
`[emitAndNotifyCompletion] getAgent(${run.agentId}) failed; skipping budget-paused notification: ${error instanceof Error ? error.message : String(error)}`,
@@ -294,7 +294,7 @@ export function triggerSelfWake(
if (hadDeferredWakes || isQuitting() || destroyed) return;
try {
const actionableTasks = db.listAgentTasks(run.agentId, run.companyId, ["todo", "in_progress"]);
const actionableTasks = db.tasks.listAgentTasks(run.agentId, run.companyId, ["todo", "in_progress"]);
const hasWorkToContinue = actionableTasks.length > 0 || hasUnfinishedTeamBuilding(db, run.agentId, run.companyId);
if (!hasWorkToContinue) return;
@@ -305,7 +305,7 @@ export function triggerSelfWake(
);
// Escalate to manager since agent is stuck
try {
const chain = db.getChainOfCommand(run.agentId);
const chain = db.agents.getChainOfCommand(run.agentId);
if (chain.length > 0) {
wakeAgentIfPossible(chain[0].id, run.companyId, "report_stuck");
}
@@ -342,9 +342,9 @@ function hasUnfinishedTeamBuilding(
companyId: string,
): boolean {
try {
const agent = db.getAgent(agentId);
const agent = db.entityCrud.getAgent(agentId);
if (agent.reportsTo !== null) return false;
const activeReports = db
const activeReports = db.agents
.getDirectReports(agentId, companyId)
.filter((r) => r.status !== "pending_approval" && r.status !== "terminated");
if (activeReports.length > 0) return false;
+1 -1
View File
@@ -38,7 +38,7 @@ export async function handleRunLog(
try {
const run = db.getRun(event.runId);
if (run.taskId) {
db.renewTaskLease(run.taskId, run.id);
db.tasks.renewTaskLease(run.taskId, run.id);
}
leaseRenewalMap.set(event.runId, now);
} catch (err) {
@@ -32,7 +32,7 @@ export function handleRunStatus(
try {
const run = db.getRun(event.runId);
if (run.taskId) {
db.renewTaskLease(run.taskId, run.id);
db.tasks.renewTaskLease(run.taskId, run.id);
}
onRunStarted?.(run.id, run.taskId, run.agentId, run.companyId);
} catch (err) {
@@ -11,12 +11,16 @@
export interface EscalationDeps {
db: {
getTaskRetryCount: (taskId: string) => number;
incrementTaskRetryCount: (taskId: string) => void;
resetTaskRetryCount: (taskId: string) => void;
getChainOfCommand: (agentId: string) => Array<{ id: string; name: string }>;
getCeoForCompany: (companyId: string) => { id: string; name: string } | null;
advanceTaskStatus: (taskId: string, status: string, note: string) => unknown;
tasks: {
getTaskRetryCount: (taskId: string) => number;
incrementTaskRetryCount: (taskId: string) => void;
resetTaskRetryCount: (taskId: string) => void;
advanceTaskStatus: (taskId: string, status: string, note: string) => unknown;
};
agents: {
getChainOfCommand: (agentId: string) => Array<{ id: string; name: string }>;
getCeoForCompany: (companyId: string) => { id: string; name: string } | null;
};
};
wakeAgentIfPossible: (agentId: string, companyId: string, trigger: string) => unknown;
notify: (title: string, body: string) => void;
@@ -42,11 +46,11 @@ export function handleFailureEscalation(
scheduleRetry: (fn: () => void, delayMs: number) => void,
): EscalationResult {
const { db, wakeAgentIfPossible, notify, logger } = deps;
const retryCount = db.getTaskRetryCount(run.taskId);
const retryCount = db.tasks.getTaskRetryCount(run.taskId);
if (retryCount < maxRetryAttempts) {
db.incrementTaskRetryCount(run.taskId);
db.advanceTaskStatus(
db.tasks.incrementTaskRetryCount(run.taskId);
db.tasks.advanceTaskStatus(
run.taskId,
"todo",
`Run ${eventStatus} (attempt ${retryCount + 1}/${maxRetryAttempts}). Auto-retrying after ${retryCooldownMs / 1000}s cooldown.`,
@@ -61,14 +65,14 @@ export function handleFailureEscalation(
}
// Retry limit reached — escalate up the chain
db.resetTaskRetryCount(run.taskId);
db.tasks.resetTaskRetryCount(run.taskId);
logger.warn(
`[escalation] Task ${run.taskId} failed ${maxRetryAttempts} times. Escalating to manager.`,
);
let escalated = false;
try {
const chain = db.getChainOfCommand(run.agentId);
const chain = db.agents.getChainOfCommand(run.agentId);
if (chain.length > 0) {
wakeAgentIfPossible(chain[0].id, run.companyId, "report_failed");
escalated = true;
@@ -84,7 +88,7 @@ export function handleFailureEscalation(
if (!escalated) {
try {
const ceo = db.getCeoForCompany(run.companyId);
const ceo = db.agents.getCeoForCompany(run.companyId);
if (ceo) {
wakeAgentIfPossible(ceo.id, run.companyId, "report_failed");
escalated = true;
@@ -120,7 +124,7 @@ export function handleSuccessReset(
logger?: EscalationDeps["logger"],
): void {
try {
db.resetTaskRetryCount(taskId);
db.tasks.resetTaskRetryCount(taskId);
} catch (error) {
logger?.warn(
`[escalation] resetTaskRetryCount failed for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`,