fix: push a FAILED notification when a scheduled run dies without reporting

sync pushes its result only from the end of a run it finished, so a crash or an early exit sent nothing, while the providers that survived kept pushing OK. The systemd unit now runs scheduling/run-sync.sh, which keeps the per-provider loop and pushes a high-priority failure, with the exception class only, for any run that exited non-zero without the app's own report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LbnmGHnFqDjyhPcCg1SEfF
This commit is contained in:
JesseMarkowitz
2026-10-05 07:14:16 -04:00
co-authored by Claude Opus 5.5
parent 64068bb19b
commit 23c6e1f512
4 changed files with 111 additions and 11 deletions
+10 -10
View File
@@ -44,10 +44,12 @@ fi
[ ${#PROVIDERS[@]} -eq 0 ] && PROVIDERS=("all")
if [ ! -x "$REPO/ai-chat-exporter" ]; then
echo "error: $REPO/ai-chat-exporter is missing or not executable." >&2
exit 1
fi
for f in "$REPO/ai-chat-exporter" "$REPO/scheduling/run-sync.sh"; do
if [ ! -x "$f" ]; then
echo "error: $f is missing or not executable." >&2
exit 1
fi
done
mkdir -p "$UNIT_DIR"
@@ -65,12 +67,10 @@ mkdir -p "$UNIT_DIR"
echo "Type=oneshot"
echo "WorkingDirectory=$REPO"
echo "Environment=AI_CHAT_EXPORTER_QUIET_CWD=1"
# One ExecStart per provider would stop at the first failure, silently
# skipping the rest — an expired ChatGPT token would mean codex never runs.
# Loop instead, so every provider is attempted and the unit still reports
# failure if any of them failed.
printf 'ExecStart=/bin/sh -c '\''rc=0; for p in %s; do "$0" sync --provider "$p" --joplin-optional || rc=1; done; exit $rc'\'' %s\n' \
"${PROVIDERS[*]}" "$REPO/ai-chat-exporter"
echo "Environment=AICHAT_SYNC_UNIT=$NAME"
# run-sync.sh attempts every provider even after one fails, and pushes a
# FAILED notification for any run that died without sending its own.
echo "ExecStart=$REPO/scheduling/run-sync.sh ${PROVIDERS[*]}"
} > "$UNIT_DIR/$NAME.service"
# Persistent=true runs a missed schedule at the next boot — the machine being