# Waiting, following and recovering

An observer reads existing work. Ending its wait does not cancel a job, stop a recording or detach a browser view.

## Choose the observation boundary

```sh
olenji jobs wait JOB_ID --wait-timeout 30 --json
olenji events SESSION_ID --after CURSOR --follow --seconds 30 --committed-only --jsonl
olenji ui configure VIEW_ID --config '{"layout":"bilingual","target_language":"tr"}' --wait-applied 5 --json
olenji tui SESSION_ID --seconds 30
```

Job waits and event follow establish the service once before starting their observation timer. This initial connection/startup has its existing lifecycle and is separate from `--wait-timeout` or `--seconds`. View waits start after the view mutation. An interactive terminal timer starts after its initial snapshot; machine `tui --json` returns one snapshot.

Later observer polls check the current service's workspace identity and version without starting a replacement daemon. Each read uses the same address that passed its health probe, even if service discovery changes during a concurrent restart.

## Interpret completion and failure

| Outcome | Meaning and next action |
| --- | --- |
| Job result | The observed job completed within the observation budget. Inspect its result. |
| `WAIT_TIMEOUT` with `job_id` | The wait ended; work was not cancelled. Resume waiting on that same ID or inspect `jobs get`. |
| Event follow reaches `--seconds` | The stream ends cleanly without a final document. Save the last event/reset checkpoint. |
| View has `applied:false` and `wait_timed_out:true` | The requested presentation has not been confirmed within this wait. Keep its last known revision and query again before claiming it is visible. |
| `SERVICE_UNAVAILABLE` | The observed owner disappeared or did not pass its health probe. Inspect service status; restart deliberately if appropriate, then inspect recovery before resuming. |
| `SERVICE_VERSION_MISMATCH` | The service belongs to this workspace but runs another application version. Finish active work and explicitly stop/restart with the intended installation. |
| `RESPONSE_TOO_LARGE` | Reduce the event page/window or export the content. Repeating the same oversized observation is not a repair. |

A follow error includes `details.cursor` and `details.session_id`. This cursor covers the pages already consumed, including empty filtered pages. Resume with `--after` only after checking the service's recovered state. A `stream.reset` frame means the saved cursor is ahead of the restored database: read a new atomic snapshot and resume from its cursor. A `segments.replacement_started` event also requires a snapshot before applying its constituent edits.

Ctrl-C returns exit code 130 and leaves already admitted work alone. A closed downstream pipe exits quietly. Event following does not read or close the caller's stdin. Explicit `jobs cancel` and `live stop` remain separate operations.

## Time and size bounds

Observation uses monotonic time. Sleep durations and network phase timeouts shrink to the remaining budget; expiry is checked before/after blocking phases and between yielded response chunks. A response that finishes after expiry is not accepted as timely completion or acknowledgement.

These synchronous checks do not promise hard real-time interruption of an OS call. Scheduling, an in-progress read and JSON decoding can finish after the nominal deadline. Initial bootstrap is also outside the observation timer, as described above.

Observer bodies accept at most 8 MiB, and health probes accept at most 16 KiB. Requests ask for identity encoding, check declared and streamed byte sizes and close the response on completion, error or cancellation. Normal one-shot API data reads and streamed exports retain their existing behavior. The terminal uses the same observer transport for refresh/reconnect; see [TERMINAL.md](/docs/1.3.0/terminal.md).
