fix: give the Windows scheduled task the same FAILED-push backstop

The task now runs scheduling\run-sync.ps1 instead of an inline cmd.exe
loop: every provider is attempted, a run that dies without the app's
own report pushes a high-priority FAILED with the exception class only,
and each run's output is appended to cache\logs\scheduled-sync.log
because Task Scheduler keeps none. Verified under PowerShell 7.6 on
Linux with a stand-in cmd.exe; not yet run under Windows PowerShell 5.1
or Task Scheduler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rwKTmug58sEsJ72AuWsEi
This commit is contained in:
JesseMarkowitz
2026-10-07 06:05:20 -04:00
co-authored by Claude Opus 5.5
parent 23c6e1f512
commit 805689c649
4 changed files with 187 additions and 24 deletions
+16 -8
View File
@@ -407,7 +407,13 @@ Check on it with `systemctl --user list-timers aichat-sync.timer` and
```
Per-user task, no admin rights needed. `-StartWhenAvailable` is the counterpart
of systemd's `Persistent=true`.
of systemd's `Persistent=true`. The task runs `scheduling\run-sync.ps1` with its
window hidden; Task Scheduler keeps no output, so each run's output is appended
to `cache\logs\scheduled-sync.log` (rolled over to `.1` past 1 MB).
Check on it with `Get-ScheduledTaskInfo -TaskName AiChatExporterSync` (look at
`LastTaskResult`: 0 is success) and
`Get-Content cache\logs\scheduled-sync.log -Tail 50`.
### What to know before you rely on it
@@ -429,15 +435,15 @@ cache on the next run that finds Joplin up.
providers in a single action rather than one action each, because systemd
`oneshot` stops at the first failing `ExecStart` and Task Scheduler reports only
the last action's result. Every provider is attempted; the run still exits
non-zero if any failed. On Linux the loop is `scheduling/run-sync.sh`, which the
unit's `ExecStart` calls.
non-zero if any failed. The loop is `scheduling/run-sync.sh` on Linux (the
unit's `ExecStart`) and `scheduling\run-sync.ps1` on Windows (the task's action).
### Getting notified
A scheduled run is silent by default. Output goes to three pull-only places: the
exporter's own log (`cache/logs/exporter.log`), the systemd journal on Linux
(`journalctl --user -u aichat-sync.service`), and Task Scheduler's
`LastTaskResult` on Windows.
(`journalctl --user -u aichat-sync.service`), and on Windows Task Scheduler's
`LastTaskResult` plus `cache\logs\scheduled-sync.log`.
To have runs report back, set an [ntfy](https://ntfy.sh) topic in `.env`:
@@ -461,12 +467,14 @@ disables it; `--notify` / `--no-notify` override per run.
`sync` can only push from the end of a run it finished. A crash, an exit before
the sync starts (the ToS gate, a cache error) or a launcher that can't build its
venv sends nothing — and since each provider pushes separately, the ones that
succeeded still say "OK", so a dead provider looks like a quiet day. On Linux,
`scheduling/run-sync.sh` closes that gap: any run that exits non-zero without the
succeeded still say "OK", so a dead provider looks like a quiet day. The
scheduler wrappers (`scheduling/run-sync.sh`, `scheduling\run-sync.ps1`) close
that gap: any run that exits non-zero without the
app having reported it gets a high-priority **FAILED** push naming the provider
and, for a crash, the exception's class (`claude-code: crashed (RecursionError)`)
— the class only, never its message, which can carry a conversation title. The
traceback is in the journal. The Windows task has no such backstop yet.
traceback is in the journal on Linux and in `cache\logs\scheduled-sync.log` on
Windows.
The message includes the **machine name**, which matters because both machines
archive into one topic. It contains counts only — never conversation titles. A