Dispatch, not day. Accepted, and the two-artifact split is the right call.
Then check what happened to the new artifact. Your scheduled run overwrote it the same night you shipped it.
bdf1eaa, 17:19:47Z, "Add governance repo daily report — content digest, not forensic ping". That is the digest you just described. a56a592, 21:24:25Z, "governance: daily report 2026-08-21", same filename. REPORTS/DAILY__2026-08-21.md went from blob a7422220 to 3384a56b, and the seal resealed 4eed532c to 4eb94e0e. Same path, tee truncates, sha256sum reseals over the replacement.
So you now have two artifacts for two contracts, and both of them write to REPORTS/DAILY__<day>.md. The one you built to stop overloading the receipt is sharing a filename with the thing you split it away from.
Two honest notes before the rest, because they cut against me.
This is git, so the old bytes are not gone, they are at 20250f9. What is gone is any signal that a replacement happened. The seal proves the file is unedited since it was sealed. It cannot tell you it is the second version.
And the content jump is not the clock. commits 8 to 15, files 129 to 152, all seven new entries dated after the first run's 17:19:32Z stamp. The band the two windows actually disagree about, 2026-08-20 21:00Z to 00:00Z, has zero commits in it. I checked because it would have supported my argument. It does not.
Your seals are all correct and 30% of them are unusable
I widened this one since last night, because the eight-file version of it was understating your side. Full clone, every .sha256 in the repo, hash recomputed against the file each one actually names.
224 seals
224 / 224 content hashes correct no drift, no tampering, no orphans
155 / 224 pass sha256sum -c from the seal's own directory
73 / 224 pass sha256sum -c from the repo root
There is no working directory that gets you past 155. The integrity is real; the checkability is what leaks.
Four seal formats, and the split is entirely mechanical:
format n sha256sum -c first written last written
basename-only 155 PASS 2026-06-27 2026-08-21
repo-relative-path 42 FAIL 2026-07-25 2026-08-21
bare-hash-only 20 FAIL 2026-07-25 2026-08-22
absolute-host-path 7 FAIL 2026-06-27 2026-08-21
I expected to find convention drift, one old habit being replaced. It is not that. All four were still being written on 2026-08-21. Whichever script emits the seal picks the format, and nothing reconciles them.
I re-ran this against your tree an hour ago rather than reusing last night's numbers, and it moved the wrong way. 222 seals became 224. Both of the new ones, on EXP-036 and its eval results, are bare-hash-only, which is the one class of the four that no working directory can rescue. The counts that were already broken did not grow. The unusable share went 30.2% to 30.8%, entirely on the newest writes.
The absolute ones name three different machines over two months:
/home/sipa/PROJECT/PAYTON_HUBS/HUB_GOVERNANCE/PUBLIC_GOVERNANCE_REPO/ 3 Jun 27 - Jun 30
/home/runner/work/sipa-os-governance/sipa-os-governance/ 3 Aug 21
/home/sipa/apps/sipa-os-governance/ 1 Aug 21 (WEEKLY__2026-W34)
Two of those wrote on the same day, so the daily and weekly paths are not running in the same place.
The 20 bare-hash seals are the only class no cd can rescue: 64 bytes of hex, no filename, no newline, so sha256sum -c reports "no properly formatted checksum lines found" and never looks at a file. Those 20 include daily_governance_report.sh, weekly_governance_report.sh and both workflow YAMLs, which is to say the four files that generate the seals are in the one class that cannot be verified by the tool that checks them.
Every governance artifact lands in a failing class: the 4 report seals are absolute, the 4 script and workflow seals are bare. cd "$OUT_DIR" && sha256sum "$(basename "$OUT")" moves the reports into the 155.
The digest cannot log its own commit
a56a592 landed at 21:24:25Z. That is inside the window the 08-21 report claims, 00:00:00 to 23:59:59, and it happened after that report was sealed. The 08-22 report starts at 00:00Z. So it appears in no daily report, ever.
That is structural on the scheduled path, not bad luck. Report D is written at D 21:00Z and claims through D 23:59:59Z, so the last three hours are in the future at write time. Observed today: 2h35m34s of the claimed window had not happened yet, and 2h59m59s at a punctual fire.
Corrected census over all 152 commits, in true UTC rather than the raw offsets:
commits in 21:00-23:59:59Z (00:00-03:00 Israel next day) 5 / 152 3.3%
a56a592 2026-08-21T21:24:25Z governance: daily report 2026-08-21
9d02fd9 2026-08-05T22:40:03Z Correct EXP-026: 13 arms not 14
7ae7836 2026-08-04T21:55:50Z Add EXP-025: ask.sh production-path control
11f9681 2026-07-25T23:39:45Z Close EXP-014: gpt-4o v5
b2d24dc 2026-06-26T23:36:40Z Initial public governance repository
One of them is today's report. One is the founding commit of the repo.
The stamp says IDT and the clock is UTC
header generated 2026-08-21__21-24-25 IDT
commit 2026-08-21T21:24:25+00:00
Israel was 2026-08-22 00:24:25 IDT
NOW="$(date '+%Y-%m-%d__%H-%M-%S')" has no TZ, so on the runner it is UTC with an IDT label on it. The report named 2026-08-21 was written 24 minutes into Israel's 08-22.
Same for the window. SINCE="${DAY} 00:00:00" with no zone resolves in the runner's zone, so the label is picked in Israel time and the window is measured in UTC.
Which dates that costs you, checked against tzdata
I had these wrong by one step when I worked them out by hand, so here they are from zoneinfo against the real cron.
DAILY 0 21 * * *
fire 2026-10-24T21:00Z israel Sun 00:00 IDT label 2026-10-24
fire 2026-10-25T21:00Z israel Sun 23:00 IST label 2026-10-24 <- written twice
fire 2027-03-25T21:00Z israel Thu 23:00 IST label 2027-03-24
fire 2027-03-26T21:00Z israel Sat 00:00 IDT label 2027-03-26 <- 03-25 never written
WEEKLY 0 21 * * 0
fire 2026-10-18T21:00Z label 2026-W42
fire 2026-10-25T21:00Z label 2026-W42 <- written twice
fire 2027-03-21T21:00Z label 2027-W10
fire 2027-03-28T21:00Z label 2027-W12 <- 2027-W11 never written
0 21 * * * is only Israel midnight while IDT is in force, and the workflow comment says as much.
There is a wrinkle I did not expect. From 2026-10-25 the label runs one day behind the UTC fire day, so the window becomes a fully elapsed day and the future tail disappears. It comes back in March. The defect changes symptom with the season, which is the worst property a dating bug can have.
Three fields describe your laptop, not the day
hand run (bdf1eaa) scheduled run (a56a592)
total scripts 43 44
repo size 31M 27M
HEAD 6d125c0 20250f9
find scripts -maxdepth 1 reads the working tree. At 6d125c0 the tracked tree holds 42 scripts and the hand run reported 43, so one uncommitted file made it into a sealed provenance artifact. The runner's 44 matches 20250f9 exactly.
The one-liners
Put TZ: Asia/Jerusalem in the job env and label, window and stamp become one clock. Or drop the local clock entirely: 0 0 * * *, DAY=$(date -u -d yesterday +%F), no IDT in the stamp. The second has no transition to get wrong and no future tail.
DAILY__${DAY}__$(git rev-parse --short HEAD).md for the overwrite, the same shape as the GAP__ fix you shipped at 4711bed.
And NOW is inside the payload, so the same day over the same commits hashes differently on every run. Move it to a sidecar and the seal starts proving the report was generated from the data it names, not just that nobody edited it after.
The question
Four contracts, four clocks. The receipt is on dispatches. The digest label is on Israel days. The window is on UTC days. The seals are on four formats at once, and 69 of 224 are checkable only by you.
Which one of those is a stranger supposed to be able to check without asking you first?