# Host Lifecycle Step Logging Design

## Goal
Provide granular, live progress feedback in the web GUI during lifecycle operations (`initialize`, `start`, `stop`, `delete`) without exposing sensitive internal paths or raw subprocess mechanics unless they fail.

## Approach
Currently, `l4d2ctl` executes operations silently unless a subprocess fails. `l4d2web` captures `stdout` and `stderr` from `l4d2ctl` and pushes it to the browser via Server-Sent Events.

We will modify `l4d2host/instances.py` to emit safe, high-level step markers to `stdout`.

Since `l4d2web` uses `subprocess.Popen(..., stdout=subprocess.PIPE)` to execute `l4d2ctl`, any standard Python `print(..., flush=True)` in `l4d2host` will be naturally captured by `job_worker.py` and forwarded to the GUI as `stdout` events.

## Logging Strategy

We will introduce an explicit `_emit_step(msg: str, on_stdout: Callable | None, passthrough: bool)` helper in `l4d2host/instances.py` to correctly route step output based on the calling context:
- If `on_stdout` is provided (e.g. programmatic use), call it.
- If `passthrough` is true (e.g. `l4d2ctl` CLI), `print(..., flush=True)`.

### Step Messages

**`initialize_instance`**
- `creating instance directories...`
- `writing instance.env...`
- `writing server.cfg...`
- `initialization complete.`

**`start_instance`**
- `mounting runtime overlay...`
- `copying server.cfg to runtime...`
- `starting systemd service...`
- `start complete.`

**`stop_instance`**
- `stopping systemd service...`
- `unmounting runtime overlay...`
- `stop complete.`

**`delete_instance`**
- `stopping systemd service (if running)...`
- `unmounting runtime overlay (if mounted)...`
- `removing instance files...`
- `delete complete.`

## File Changes

- **`l4d2host/instances.py`**
  - Add `_emit_step` helper.
  - Insert calls to `_emit_step` at key locations in all lifecycle functions.
  
- **`l4d2web/services/job_worker.py`**
  - Add synthetic web-layer boundary logs (`starting initialize for test-server`, `finished initialize successfully`) to clearly distinguish the boundaries between multiple `l4d2ctl` operations in compound jobs like `start` (which calls initialize then start).

## Safety & Secrets
- `print` statements must **not** include full absolute paths (e.g. avoid printing `/var/lib/left4me/runtime/alpha/merged`).
- `print` statements must **not** echo spec data or env vars that might contain future RCON passwords or sensitive args.

## Test Impact
- `test_l4d2_facade.py` and `test_job_worker.py` that use fake `run_command` handlers might need to explicitly emit stdout if tests assert exact sequences.
- Existing tests that call `initialize_instance` without `passthrough` will silently ignore steps as expected.
