Addresses review findings before Slice 5 sandbox work. Resolver primitives: - resolveOutcome maps an attempt outcome to retry-or-terminal; removed the no-op isTerminalClassification. - WORK_STATUS_FOR_OUTCOME preserves real terminal Work status instead of collapsing everything back to ready. - Lifecycle: completed is terminal, cancelled reopens only to ready, and the invalid awaiting-design-approval -> awaiting-definition-approval reopening is gone. Execution (workExecution.ts): - finishAttempt replaces completeAttempt: auto-retries within the kit budget and settles Work at the real classification (Succeeded->completed, PermanentFailure/BudgetExhausted->failed, NeedsInput->needs-input, Blocked->blocked). No Work stays silently runnable after a failure. - startSimulatedExecution validates sliceId against the current approved Design (foreign ids rejected; defaults to the first slice) and advances slice status running -> completed/ready. - retrySimulatedExecution is now an explicit user restart with a retryable- state guard, not the automatic resolver path. - reconcileExpiredAttempts is bounded: a dead lease terminates as Blocked, resumes within budget or settles the Run/Work so nothing runs forever. - crons.ts runs the reconciler every 30s, string-referenced so it does not depend on the stale codegen. Planning (workPlanning.ts): - saveDefinition/saveDesign reject revision while a Run is executing. - submitQuestion validates and persists a durable workQuestions row instead of discarding planner questions. - Design revision invalidates active design approvals. Verification: primitives 69 tests (+4), backend 22 tests (+10) covering retry/cancel/failure/restart, slice validation, reconciliation, the revision guard, and question persistence. Root typecheck, web+agents build, and the configured Ultracite gate (53 files) all pass. package.json: the recurring check gate now covers workExecution, workPlanning, crons, resolver, and work-lifecycle.
20 lines
525 B
TypeScript
20 lines
525 B
TypeScript
import { cronJobs, makeFunctionReference } from "convex/server";
|
|
|
|
// Reconciles attempts whose worker lease expired (crash/restart). The target
|
|
// is referenced by string so this file does not depend on regenerated codegen.
|
|
const reconcileRef = makeFunctionReference<
|
|
"mutation",
|
|
Record<string, never>,
|
|
{ reconciled: number } | null
|
|
>("workExecution:reconcileExpiredAttempts");
|
|
|
|
const crons = cronJobs();
|
|
|
|
crons.interval(
|
|
"reconcile expired work attempts",
|
|
{ seconds: 30 },
|
|
reconcileRef
|
|
);
|
|
|
|
export default crons;
|