trader.daemon.preflight module

Startup checks for the daemon.

An unattended process must refuse to start rather than run for hours in a state a human would have spotted in seconds. The checks are split from the CLI so each is testable without a runner, and split from each other so a single startup reports every problem — telling someone about one missing dependency at a time costs one restart per dependency.

trader.daemon.preflight.confirm_live_trading(*, is_live, isatty, ask)[source]

Whether to proceed when the account is not paper.

On a terminal this asks. Without one it does not ask and does not refuse — it logs and proceeds. That is a deliberate choice with a known cost: launchd gives the daemon no TTY, so an unattended live daemon starts unconfirmed. See the 2026-08-03 design doc; do not “fix” this into a prompt, which under launchd would block on stdin forever and the daemon would silently never trade.

This is a speed bump for a human, not a control. The safety gate (TRADING_MODE=live plus LIVE_TRADING_ENABLED=true) and assert_live_orders_allowed() before every submission are the controls.

Parameters:
  • is_live (bool)

  • isatty (bool)

  • ask (Callable[[str], bool])

Return type:

bool

trader.daemon.preflight.preflight_failures(*, database_url, strategy_entries, llm_health)[source]

Every reason the daemon should not start, as readable sentences.

Returns an empty list when everything is in order. Never raises for a failed check — a check that blows up is a failure to report, not a traceback to show.

Parameters:
  • database_url (str)

  • strategy_entries (Sequence[StrategyConfig])

  • llm_health (Callable[[], str] | None)

Return type:

list[str]