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.
Domain primitives: versioned WorkDefinition/DesignPacket with risk, questions,
and approval gates; lifecycle transition table with invalidation rules;
Resolver (Run/Attempt/outcomes/CodingKitV0); provider-neutral HarnessRuntime
with normalized events and a deterministic FakeHarnessLive that always reaches
a terminal classification and never claims implementation.
Convex durable model: workDefinitions, workQuestions, workApprovals,
designPackets, workSlices, workRuns, workAttempts, workAttemptEvents tables;
broadened works.status union; generalized workEvents with optional signalId,
referenceId, and payloadJson. Authenticated commands for definition request/
save/revise/approve, question answer/withdraw, design save/revise/approve, and
simulated execution start/cancel/retry with leased attempts, checkpointed
events, and expired-lease reconciliation.
Private work-planner FLUE agent with proposal-only tools (definition, design,
question). Convex validates and stores every proposal; FLUE never approves or
advances Work.
Expanded Work card with Outcome, Design, and Build sections wired to the new
mutations. Slice 1 conversation and provenance preserved.