# ADR-0020: TrapOS Boot Lifecycle

## Status

Accepted.

## Context

CraftOS runs `/startup/*` files inside its own shell and expects them to return. TrapOS needs a long-lived init-like process instead: it creates `_G.bootEventLoop`, starts autostart servers, and keeps the user shell and event loop alive together with `parallel.waitForAny`.

The old `startup/servers.lua` name hid that role, and the installer executed it directly after install. That produced a nested boot path where the installer shell, the CraftOS shell, and the TrapOS shell were all active, and where the orchestrator's shutdown behavior could stop the machine before the installer restored its working directory.

## Decision

TrapOS has one startup orchestrator: `startup/boot.lua`. It is treated as the init process for a TrapOS session.

`programs/motd.lua` owns the banner and is invoked by `startup/boot.lua` before autostart servers run. `/startup/` should contain only the boot orchestrator for the TrapOS boot package.

Session-end behavior is controlled by `trapos.on_session_end`:

- `shutdown` is the default and is also used for unset or invalid values.
- `reboot` reboots when the TrapOS shell exits.
- `relaunch` starts a fresh shell when the current one exits, re-reading the setting after each shell session so the policy can be changed before exiting again.

The previous `trapos.shutdown_on_shell_exit` setting is replaced without a migration shim. It was not documented or persisted as package state.

The installer no longer executes the boot orchestrator. Full installs run `ccpm update`, `ccpm install trapos`, `trapos-postinstall`, restore the previous shell directory, print a reboot message, and call `os.reboot()`. `--cpm-only` still returns without rebooting.

`startup/boot.lua` self-heals the known stale startup files left by package upgrades from older versions: `/startup/servers.lua` and `/startup/motd.lua`. This prevents two startup orchestrators from coexisting after `ccpm upgrade` installs the renamed files but does not prune removed package files.

## Consequences

Fresh install and normal power-on use the same boot path.

Exiting the shell never drops to a bare CraftOS prompt with no TrapOS event loop. The default remains shutdown, while reboot and relaunch are explicit local policies.

Upgraded machines converge on the new `/startup/` layout in one boot.

General pruning of removed package files during `ccpm install --force` or `ccpm upgrade` remains future work.
