--- type: guide title: Runtime Verification Guide description: Tester workflow for validating root cron startup, unprivileged bot execution, retry events, and persistent data behavior. tags: [guide, tester, docker, runtime] timestamp: 2026-08-04T20:44:00Z --- # Setup 1. Copy `.env.example` to `.env` and provide valid required values. 2. Build and start the service: ```bash docker compose up --build -d ``` 3. Follow container output: ```bash docker compose logs -f bot ``` # Expected Runtime Behavior The container remains running with `cron -f` as its foreground process. Startup output includes the configured `RUN_AT` and `TZ`. The scheduled cron command invokes `/usr/local/bin/run-bot.sh`, which runs the Python bot as user `bot`, not root. The host `./data` directory should contain the synchronized `blog/` clone and, after the state store is loaded, `posted.json`. Both are under the one `/app/data` mount. # Manual Run Run the same application command without waiting for cron: ```bash docker compose exec bot /usr/local/bin/python -m tenbackward ``` A valid run exits `0`. A configuration failure exits `2`; an exhausted pipeline retry budget exits `1`. # Retry Checks To exercise transient failure handling, use a test repository or injected test double that fails once and then succeeds. Verify JSON events contain: | Event | Expected fields | |---|---| | `retry_attempt` | `operation`, `attempt`, and the original `error` text. | | `retry_exhausted` | Final `operation`, total `attempts`, and `error` text when all attempts fail. | | `run_complete` | Counters and `posted_ids` only after a successful pass. | With `MAX_RETRIES=0`, one attempt is still made and no sleep occurs. With a larger value, delays occur only between attempts and follow powers of two beginning at one second. # Configuration Checks Remove a required variable from `.env` and restart the service. The entrypoint should report the missing variable before cron starts. If the shell check is bypassed and the Python module runs directly, `configuration_error` should identify the missing key and return exit code `2` rather than silently substituting an application default. # Persistence and Failure Safety After a successful publication, inspect `/app/data/posted.json` and confirm new relative post paths appear under the `posted` list. If Mastodon publishing fails, the path must not be recorded; a later retry should be able to publish it again. # Key Visual/Observable Elements This service has no graphical UI. Test-facing outputs are: * Container status and `docker compose logs` output. * JSON-per-line startup, retry, failure, and completion events. * Exit codes from manual runs. * `/app/data/blog` and `/app/data/posted.json` on the mounted host directory. # Related * [Daily Run Guide](/guides/daily-run.md) * [Job 1089 Runtime Changes](/architecture/runtime-changes.md) * [Environment Variable Setup](/operations/environment-setup.md) * [Cron Lifecycle](/operations/cron-lifecycle.md)