# Safe production branch deployments

Lumi can deploy the stable `main` branch or an exact published
`experimental-*` branch from **Admin > Updates > Running code branch**. This is
a managed deployment; Lumi does not change the live installation's Git
worktree. It fetches the selected branch into `data/update-cache/repo`, verifies
the core and bundled-plugin entry files, snapshots the running core and plugin
code plus the database, replaces managed application files, records the deployed
branch and commit, and then restarts.

Local data remains in place during a normal branch switch, including settings,
databases, plugin data, uploads, logs, secrets, AI models/runtimes, community
knowledge, corrections, and `node_modules`. Bundled plugin code follows the
selected branch; local-only plugins absent from that branch stay installed. The
update-aware wrapper repairs changed runtime dependencies before it starts the
new branch.

## Prerequisites

1. Start production through `npm start`, `npm run run`, or a service that runs
   `node run.js`. The wrapper recognizes Lumi's restart exit code and starts the
   deployed code after dependency verification.
2. Ensure the configured repository credential can fetch branches without an
   interactive password prompt.
3. Push the experimental branch before opening the deployment control. Only
   `main` and remote branches named `experimental-*` are accepted.
4. Keep snapshot retention high enough to retain at least the latest core
   backup. The default keeps five per target for 30 days.

## Test an experimental branch

First update production on `main` to stable `0.2.25` through the existing
**Update from repository** action. This installs the exact-branch controls on
stable, so future switches in either direction use the same verified workflow.
If a `0.2.24` host enters Experimental before taking the stable update, the
guarded compatibility bootstrap completes bundled-plugin synchronization after
the older updater installs the newest `experimental-*` branch; expect a second
restart. Merely checking metadata cannot trigger that bootstrap.

1. Open **Admin > Updates** and find **Running code branch**.
2. Confirm the page reports the expected running branch and commit.
3. Choose the exact experimental branch and select **Deploy selected branch**.
4. Review the confirmation. Keep the page open while Lumi creates the backup,
   deploys, restarts gracefully, and reconnects.
5. Verify the branch and commit after reconnection, then test the affected
   production workflows.

The same branch can be selected again for a verified repair deployment.

## Return to stable main

Use **Return safely to main**. Lumi first snapshots the running experimental
code, then deploys the current remote `main` while preserving live data. This is
the preferred normal return path because it does not intentionally rewind the
database or discard data written during the experiment.

Experimental database migrations must remain backward-compatible with `main`
when this path is expected to work. Mark experimental update metadata with
`rollback_safe: false` and document the migration when a change cannot safely be
read by the stable code.

## Emergency restore

Use **Emergency restore previous backup** only when the deployed branch cannot
run correctly enough to return through the normal branch control. It restores
both the previous core code and the database captured before deployment, so
database changes written after that snapshot may be lost.

If the normal WebUI is unavailable, start recovery mode with
`LUMI_SAFE_MODE=1 npm run run`, `node run.js --safe-mode`, or the
`data/recovery/safe-mode.flag` marker. Recovery markers and deployment state are
also visible through the production diagnostics `update_state` check.

## Failure behavior

Fetching and target verification happen before live files are touched. Once
replacement starts, failures trigger an automatic restore from the new
snapshot. If automatic restore also fails, Lumi retains the recovery marker and
snapshot for safe mode instead of silently continuing with a partial install.
