fix(scheduled-tasks): keep task fields a server build does not know

Every project-config write re-serialized normalized tasks, so a server
that shares the config file but predates a field (goal, auto-accept)
stripped it the first time any task ran. Untouched tasks now go back to
disk verbatim, a state update swaps only `state`, and only a deliberately
replaced task is serialized from the normalized shape.
This commit is contained in:
Bohdan Triapitsyn
2026-08-30 13:19:45 +03:00
parent 5fabeccd2d
commit db0bf115ad
3 changed files with 125 additions and 5 deletions
@@ -25,6 +25,13 @@ in shared project config under the project write lock:
from the winner's persisted `nextRunAt`.
- Project config writes also take a cross-process `.json.lock` file so the
read-modify-write is serialized across processes, not only within one process.
- The sharing processes may run different OpenChamber versions. Normalization
keeps only the fields a build knows, so every writer persists tasks it did
not change verbatim from disk and swaps only `state` onto a task whose state
it updated; a task goes out normalized only when it was deliberately
replaced (upsert, loop adoption). An older server touching the file after a
run therefore cannot strip fields a newer build added, such as a task's goal
or auto-accept settings.
- Lock timeout / filesystem errors on claim, manual-start, or completion state
writes always release the in-process running slot (via `finally`) and best-effort
re-arm the **next future** occurrence; they must not leave the task permanently