_data/diary.json on master is the canonical public diary. Jekyll renders it at
https://zhayitong.com/log/. There is no backend, database, credential in the site,
or second locally authoritative diary. Temporary local files are working copies.
Only publish the user’s authorized meal/workout diary subset. Never copy a private tracker wholesale. Exclude health records, BodySpec, private source/chat IDs, chat transcripts, targets, race benchmarks and images. The validator rejects unknown fields, but cannot determine whether allowed text contains private information: review every string before publishing. Git history is public and persistent.
Dates are local calendar dates in America/Los_Angeles, not UTC dates. Resolve
“today/yesterday” in that zone, or use the user’s explicit meal/workout date. Do
not invent times or convert a date-only record via UTC. Preserve stable IDs across
corrections (even a corrected date); allocate a new public ID only for a genuinely
new entry. Check existing entries before assigning an ID to a repeated report.
Days have food_log_status: not_logged, incomplete, or complete. New food
days should be incomplete; only mark complete with confirmation that the day’s
food intake is fully logged. No logged food is unknown, not zero. Totals are
computed from meals; never store competing daily totals. Keep estimates, portion
assumptions and uncertainty explicit. Workout status is completed or planned;
only completed workouts describe work actually done.
Python 3 standard library only:
python3 scripts/diary.py validate _data/diary.json
python3 -m unittest discover -s scripts -p 'test_diary.py'
python3 scripts/diary.py totals _data/diary.json
python3 scripts/diary.py apply _data/diary.json /tmp/diary-patch.json
The patch format is {"operations": [...]}. Each operation is:
{"collection":"meals","key":"meal-example-001","before":null,"after":{"...":"complete public meal entry"}}
The abbreviated after above is illustrative, not a valid entry. Use the schema
in scripts/diary.py and existing data for exact required fields. Collections are
days, meals, workouts; the key is date for days and id otherwise. before
is the complete entry originally read (or null for creation), after the complete
replacement (or null for deletion). Include a new day and its meal in one batch.
Never put private provenance in either side of a patch or in the commit message.
Updates are compare-and-swap: if current equals after, replay is a no-op; if it
equals before, the update applies; otherwise it conflicts and requires deliberate
reconciliation. Unrelated entries survive. The entire result validates before an
atomic local file replacement. Run only one local writer per working copy; remote
concurrency is protected by the GitHub blob-SHA lease below, not by the local CLI.
_data/diary.json from repository
yitongzhang/yitongzhang.github.io, ref master, using GitHub fetch_file.
Retain its exact current blob SHA. Do not publish from a stale cached snapshot.update_file with repository_full_name as above, branch: master,
path: _data/diary.json, sha equal to that fetched blob SHA, and content
equal to the complete validated result. This is an optimistic atomic update.
Keep other paths untouched for ordinary diary updates. No force push.master and the remote JSON equals the
intended merged result. Inspect the GitHub Actions pages build and deployment
run for that exact SHA until success; a commit alone is not a deployed page.
Verify https://zhayitong.com/log/ shows the entry, correct local date and totals.
Report a build/publication failure rather than claiming it is live.For authenticated git instead, start from latest master, apply the same patch, validate, commit only the diary file, and use a normal fast-forward push. If rejected, fetch latest and reapply the patch on a clean latest-master working copy; do not force or blindly resolve data conflicts. Preserve the failed attempt for diagnosis.
No scheduled job is needed: each authorized new diary report triggers this workflow.