The setup passed --no-start as the container command, which the ca-trust wrapper exec'd as a binary (exit 127); the flag does not exist in the image's entrypoint at all. Invoking /usr/local/bin/akaunting.sh with no arguments is the real one-shot contract: with AKAUNTING_SETUP=true it runs artisan install and exits without starting Apache. The swarm wait gate also accepted Shutdown as success and let the crashed job pass without ever installing; the state probe now lives in install_job_state.sh and only Complete passes, while terminal states fail loudly with the task error.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The include-gated header is the formal task_gate directive the compose-verb and compose-chdir lints read; deleting it as narration broke both. The install task name drops below the 80-char limit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AKAUNTING_SETUP=true in the rendered env re-ran the installer on every container recreation between deploys (restore drill, repair restart) and crash-looped against the installed database. The flag is gone from the env entirely: compose now installs like swarm through an ephemeral one-shot (stop, compose run --rm -e AKAUNTING_SETUP=true akaunting --no-start, up --force-recreate), included mode-agnostically from tasks/setup/{{ DEPLOYMENT_MODE }}.yml with the swarm job renamed into the same folder. The first-run gate reads the marker stat directly instead of a set_fact indirection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>