chore: Upgrade the factory eve agent to 0.39.3 (#13783)
## Why
The eve upgrade mandate requires every agent to run **0.39.1 or later**.
`apps/factory` — the only eve agent in this repository — was pinned to
`^0.22.5`. This takes it to `^0.39.3` (current `latest`) and migrates
the authored agent across the breaking changes in between.
## Migration
| eve release | Breaking change | What changed here |
| --- | --- | --- |
| 0.33.0 | `defineDynamic` accepts only `events`; a dynamic model has no
compiled default and a throwing resolver fails the turn |
`agent/agent.ts` drops `fallback` and the resolver returns a concrete
model, absorbing the unparseable-session-id case that `fallback` used to
cover |
| 0.31.0 | Continuation-token session APIs replaced with ID-addressed
handles; custom channel routes use `from(address)` /
`attachSession(sessionId)` | `agent/channels/operator.ts` starts runs
via `from(randomUUID()).send(message, options)` and reads run status via
`attachSession(sessionId).getEventStream(...)` |
| — | `session.started` no longer carries `runtime.modelId`, since a
dynamic model resolves only once a step begins |
`agent/lib/control-plane-hook.ts` records the model from the first
`step.started` of each turn; `recordAgentRunModel` writes only when the
model changed, so the ledger is not rewritten per model call |
Nothing else in the app touched a removed API: schedules still use
`defineSchedule({ cron, markdown })`, the `approval` function shorthand
and `"not-applicable"` / `"user-approval"` statuses are unchanged,
`defineSandbox` is unaffected by the custom-backend `stop()`
requirement, `vercel.json` carries no legacy `experimentalServices`
block, and the operator UI does not use the frontend bindings whose
`stop()` became `cancel()`.
## Config change worth a look
`eve` is added to `minimumReleaseAgeExclude` in `pnpm-workspace.yaml`.
The workspace gate is 48 hours and **every** `0.39.x` release is younger
than that, so without the exclusion resolution fails outright:
```
ERR_PNPM_NO_MATURE_MATCHING_VERSION Version 0.39.3 (released 3 hours ago) of eve
does not meet the minimumReleaseAge constraint
```
There is no compliant version that satisfies the mandate, so the gate
and the mandate cannot both hold. This follows the existing precedent
for first-party packages (`next`, `@next/*`, `@vercel/geistdocs`) and is
scoped to `eve` alone.
Note that this is **not** the release-age rule the factory agent is
bound by: `agent/instructions.md` and
`agent/skills/examples_maintenance.md` forbid exclusions when upgrading
**examples**, and that guardrail is enforced in `create_pull_request`
only for paths under `examples/`. This change is outside it and does not
weaken it. Happy to drop the exclusion in a follow-up once `0.39.1`
clears 48 hours (2026-08-21 04:30 UTC) if you would rather not carry it.
## Behavior change to be aware of
eve 0.33.0 made `turnPolicy: "steer"` the channel default, so a
follow-up Slack or GitHub message now cancels and replaces an active
turn instead of queueing behind it. Adopted as-is: the automated paths
are unaffected because scheduled runs and operator runs each get their
own session, and steering is the better interactive behavior. Set
`turnPolicy: "queue"` on those channels if the old wait-for-completion
behavior is preferred.
## Validation
- `pnpm install --frozen-lockfile` — lockfile consistent with the
manifests
- `tsc --noEmit -p apps/factory/tsconfig.json` — clean
- `eve info` — compile ready, 0 errors / 0 warnings, 16 tools, 2
subagents, 2 schedules, 2 skills discovered
- `pnpm test` — 24/24 passing
- `pnpm build` (`eve build && next build`) — succeeds
- `oxlint --deny-warnings`, `oxfmt --check` — clean; pre-push hooks
passed without `--no-verify`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>