Skip to content

Upgrade

Moves the site to the newest images in the registry: docker compose pull, then docker compose up -d. Placeholders are as in Install.

The ten manual steps of 2026-10-05 (verified on dev then) waited for running operations with the web stopped; on 2026-10-08 one never ended and production was down for 15 minutes. They are replaced by the steps below.

Agents of projects in a container (or Linux virtual machine) on this host no longer need a quiet moment: each one’s runner runs in the project’s container as a service of its own (ps-agent-<handle>), and the worker reaches it through the controller over a connection it makes again. Restarting the worker, the web or the controller doesn’t cut their turns, their sub-agents, or a prompt or question waiting for an answer: the worker attaches to every runner still there when it starts (startAgents in src/worker/agents/restart.ts), and again within seconds after a lost connection, and carries on with what it kept of each turn.

Agents of projects in a container on a server carry on the same way once that server has the runner this installation carries (the project’s “Update runner” card, or Settings › Servers): their runners then run as services of their own in the server’s container, reached through the server’s controller. An agent started before its server’s runner was updated runs on the worker’s connection until it next starts. A server that doesn’t answer when the worker starts (its SSH or daemon connection down) doesn’t stop its agents: they keep their state, and the worker attaches to them again as soon as the server answers.

Agents of projects on a remote host or in a Windows virtual machine carry on the same way once that host has the runner this installation carries: the runner runs there detached from the connection, and the worker attaches to it again over SSH or the host’s reverse connection.

What still interrupts:

  • Worker, for agents on an older runner: agents of projects on a remote host, in a Windows virtual machine, or in a container on a server, whose host’s runner is older than this installation’s (until its “Update runner”), still run on the worker’s connection. When the worker starts, it marks them stopped; one that was running gets a note in its chat that it stopped because the worker restarted, and starts again with the next message.
  • The project’s container or virtual machine restarting, or the runner crashing: the runner ends; the chat says so and a turn under way is started again (PROJECT.md “Runner cut off”).
  • Every controller action (not an agent’s runner) under way when the controller is recreated ends with it.

There is no schema version. Each time the web or the worker opens app.db, it applies its own schema lists from src/db/schema.ts: it creates missing tables and indexes, adds the columns in ADDED_COLUMNS that are missing, and drops the columns in DROPPED_COLUMNS and the triggers and tables in DROPPED that are still there. Each chat database gets its schema from src/db/chat-schema.ts the same way when the worker opens it.

The worker starts first, so it makes these changes. On dev the worker started in about 1 second, including the migration of the old production data. The worker logs nothing about these changes. To see them, save the schema before the upgrade and compare it after, reading as project:

Terminal window
runuser -u project -- sqlite3 -readonly /opt/ProjectStart/var/db/app.db .schema > <file>

There is no code that undoes a change; see Way back.

.env names the images by their :latest tag (Install), and each release pushes :latest. A deploy is these two commands on the host, and nothing else: nothing is waited for (agents carry on through the restarts, see What a restart ends, and an operation under way resumes its step once the worker is back).

Terminal window
docker compose -f /opt/ProjectStart/deploy/compose.yaml pull
docker compose -f /opt/ProjectStart/deploy/compose.yaml up -d

Going back to an earlier release is Way back.