# 04 · Smoke-exec cascade

`scripts/smoke-exec.sh` is a cascading shell script that exercises every
primitive `lakeshore daemon exec` supports. Cheap, comprehensive, and
unforgiving — it bails on the first failure so you fix one thing at a
time.

## Exercises

In order, one check per aspect of the exec wire:

1. Exactly one live daemon is registered (or `$LAKESHORE_DAEMON` names one).
2. Minimal stdout round-trip — `echo hi`.
3. stderr stays separated from stdout.
4. Exit code propagation — `exit 7` gives the CLI rc 7.
5. `--env` passthrough.
6. `--stdin -` piping.
7. Filesystem write/read on the daemon.
8. `--timeout` enforcement — the wire's `-2`, which bash reports as 254.
9. Long-poll spanning multiple poll windows (`sleep 40`).
10. `python3` on the host.

## Requires

- A control plane reachable at `$LAKESHORE_URL` (or a saved
  `lakeshore auth login` when it's unset).
- Exactly **one** live daemon registered in the namespace. The script
  first runs `daemon cleanup --older-than 5m --yes` to reap stale rows,
  then refuses to guess on zero or multiple.

Set `LAKESHORE_DAEMON=<id-or-label>` to skip that discovery entirely
and target a specific daemon.

## Run

```bash
# Sibling checkouts live in the container repo:
#   git clone --recurse-submodules https://github.com/dreamlake-ai/lakeshore-workspace.git
export LAKESHORE_WORKSPACE=~/lakeshore-workspace

cd "$LAKESHORE_WORKSPACE"
LAKESHORE_URL=http://localhost:8080 ./scripts/smoke-exec.sh
# or press `s` on the `smoke` pane in mprocs
```

The script prefers the local build at `lakeshore/dist/cli/index.js` so
you test what's under iteration. Set `LK=lakeshore` to run the
globally-installed npm package instead.

```bash
LK=lakeshore ./scripts/smoke-exec.sh
LAKESHORE_DAEMON=ge-debug-1 ./scripts/smoke-exec.sh
```

## Expected output

A green `✓` and a label per check, ending in
`✓ all N checks passed against <url>`. Any red `✗` stops the cascade
and the script exits 1.

## If it fails

| Check | Symptom | Likely cause |
| ---- | ------- | ------------ |
| 1 | `no live daemons registered` | The nymph pane stopped — restart it, or set `LAKESHORE_DAEMON`. |
| 1 | `N live daemons — refuse to guess` | An earlier run left daemons registered. Kill the extras (`lakeshore daemon kill --prefix ... --yes`) or set `LAKESHORE_DAEMON`. |
| 1 | `daemon list reachable` failed | The control plane is down, or auth isn't configured. |
| 4 | wrong exit code | Exit-code propagation broken between the daemon, the control plane, and the CLI. |
| 8 | `expected 254 or -2, got …` | Timeout handling. The daemon either ran past the deadline or surfaced its own error code instead of the wire's `-2`. |
| 9 | long-poll check failed | The CLI's poll window or the control plane's long-poll budget regressed. |

## Status

Manual. Tracked via the script's exit code.

## Next

→ [05 · Hello, queue-bound UDF](/python-sdk/happy-paths/05-hello-queue-udf.md)
