jq Gate Sketch for april_content_update_receipt_v1.json Weekly Catalog Row Diff - 2026

April 2027, week two after Friday March capstone: april_content_update_allowed: true, warm catalog evening left warm_catalog_ok: true. Engineering ships a second remote content build Tuesday. Producer asks "did the catalog hash drift since last week?" Someone reuses March post-fest sprint weekly jq—wrong schema: March diffs BUILD_RECEIPT sprint columns against a February closeout pointer. April needs catalog hash / content hash / RemoteLoadPath week-over-week after the capstone latch—not MERGE exception theater.
April–June 2027 content-update weeks punish teams that treat March march_post_fest_sprint_receipt_v1 as the forever weekly ritual. Summer Sale players inherit silent catalog orphans when weekly diffs still look for merge_exception_list_ok instead of catalog_sha256.
This Programming & Technical sketch ships april_content_update_receipt_v1.json (weekly instance), april_content_update_weekly_log.jsonl, verify_april_content_update.sh, gates J1–J6 on the April schema (same letter prefix as March, different receipt), and a beginner March-vs-April comparison table.
Non-repetition note: March sprint weekly jq owns post-fest BUILD_RECEIPT row diff + February closeout pointer. Warm catalog evening owns one-evening A1–A6 candidate proof. Orphan recovery owns ghost hash purge after warm GREEN. Thursday promotion review owns ten-minute promotion columns. This URL owns weekly Addressables catalog row diff after april_content_update_allowed.
Pair Friday March capstone, warm catalog, orphan recovery, Guide #50 forward, Course 288 forward, forward blog #11 Thursday content-update row review.
Why this matters now (April–June 2027 content-update weeks)
- Capstone ends March tooling —
april_content_update_allowedswitches the weekly anchor from sprint MERGE to catalog identity. - Warm ≠ weekly — A1–A6 prove one candidate evening; weekly jq proves week-over-week hash honesty.
- Orphan reintroduction — Without catalog diffs, purged ghosts return via partial uploads (orphan case study).
- Summer Sale concurrency — Higher download volume surfaces week-old catalog edges the Monday smoke never touched.
- Thursday content-update review — Forward #11 expects a weekly catalog trail, not March sprint jsonl.
Direct answer: Each ISO week after April authorize, file april_content_update_receipt_v1.json with catalog_row_diff[], append april_content_update_weekly_log.jsonl, run verify_april_content_update.sh, clear gates J1–J6, set BUILD_RECEIPT april_content_update_weekly_ok: true.
Who this sketch is for
| Audience | You will… |
|---|---|
| Beginner | Read March-vs-April table; copy bash + jq |
| Facilitator | Paste weekly catalog diff into #content-update |
| Engineer | Cron Monday 09:00 during April–June content weeks |
| Producer | Block "Sale content ship" until J3 prior-week hash resolves |
Time: ~45 minutes first weekly template; ~5 minutes per week after scripts pin.
Beginner path — March weekly vs April weekly
Memorize one sentence: March weekly = sprint BUILD_RECEIPT truth; April weekly = remote catalog identity.
| Question | March sprint jq | This April catalog jq |
|---|---|---|
| When? | ISO weeks during post-fest sprint | ISO weeks after april_content_update_allowed |
| Log file | march_post_fest_sprint_weekly_log.jsonl |
april_content_update_weekly_log.jsonl |
| Anchor | Prior week + February closeout pointer | Prior week + warm catalog / capstone pointer |
| Diff fields | build_label, evidence ok, MERGE ok |
catalog_sha256, content_sha256, remote_load_path, warm_catalog_ok |
| Prereq | march_post_fest_evidence_ok |
april_content_update_allowed + preferable warm_catalog_ok |
| Wrong reuse | Copying hourly fest jsonl | Copying March sprint schema into April |
Beginner mistake: Appending March sprint lines in May—use a new jsonl and new schema once April content work starts.
Format ladder (April content-update evidence)
| Artifact | Role |
|---|---|
| Friday March capstone | Latches april_content_update_allowed |
| Warm catalog evening | Candidate A1–A6 proof |
| Orphan recovery | Ghost hash purge R1–R6 |
| This jq sketch | Weekly catalog row diff J1–J6 |
| Forward #11 Thursday content-update row review | Ten-minute promote ritual |
| March sprint jq | Cousin cadence, different columns |
Order: Capstone → warm evening → (orphan recovery if needed) → weekly catalog jq → Thursday promote review.
Developer path — gates J1–J6 (April schema)
These J gates belong to april_content_update_receipt_v1—not March sprint J1–J6.
| Gate | Pass criterion |
|---|---|
| J1 | Receipt schema == "april_content_update_receipt_v1" and iso_week set |
| J2 | Capstone/warm pointer resolves (april_content_update_allowed true; warm path present or waived) |
| J3 | Prior ISO week jsonl line exists (or week-1 bootstrap note) |
| J4 | catalog_sha256 and content_sha256 non-empty and match named files or CDN smoke note |
| J5 | catalog_row_diff[] honest (no silent hash swaps without delta rows) |
| J6 | Receipt filed; BUILD_RECEIPT april_content_update_weekly_ok: true |
april_content_update_receipt_v1.json (weekly template)
{
"schema": "april_content_update_receipt_v1",
"content_window": "2027-04-content-update",
"iso_week": "2027-W15",
"build_label": "content-2027-04-w15",
"capstone_pointer": {
"path": "release-evidence/post-fest/sprint-2027-W13/march_capstone_closeout_receipt_v1.json",
"april_content_update_allowed": true
},
"warm_pointer": {
"path": "release-evidence/april-content/april_content_update_warm_catalog_receipt_v1.json",
"warm_catalog_ok": true,
"catalog_sha256_at_warm": "sha256:aaa111…"
},
"snapshot": {
"catalog_sha256": "sha256:ccc333…",
"content_sha256": "sha256:ddd444…",
"remote_load_path": "https://cdn.example.com/addressables/april-2027/",
"warm_catalog_ok": true,
"remote_catalog_orphan_recovery_ok": true,
"bundle_count": 14
},
"catalog_row_diff": [
{
"field": "catalog_sha256",
"before": "sha256:aaa111…",
"after": "sha256:ccc333…",
"delta": "new_catalog_build"
},
{
"field": "content_sha256",
"before": "sha256:bbb222…",
"after": "sha256:ddd444…",
"delta": "new_content_build"
},
{
"field": "remote_load_path",
"before": "https://cdn.example.com/addressables/april-2027/",
"after": "https://cdn.example.com/addressables/april-2027/",
"delta": "unchanged"
},
{
"field": "bundle_count",
"before": 12,
"after": 14,
"delta": "+2"
}
],
"gates": {
"J1": "GREEN",
"J2": "GREEN",
"J3": "GREEN",
"J4": "GREEN",
"J5": "GREEN",
"J6": "GREEN"
},
"april_content_update_weekly_ok": true,
"notes": "Second April content build; orphan recovery still GREEN"
}
Weekly log (jsonl)
release-evidence/april-content/april_content_update_weekly_log.jsonl — one line per ISO week:
{"iso_week":"2027-W14","catalog_sha256":"sha256:aaa111…","content_sha256":"sha256:bbb222…","remote_load_path":"https://cdn.example.com/addressables/april-2027/","bundle_count":12,"receipt":"release-evidence/april-content/weekly/2027-W14.json"}
{"iso_week":"2027-W15","catalog_sha256":"sha256:ccc333…","content_sha256":"sha256:ddd444…","remote_load_path":"https://cdn.example.com/addressables/april-2027/","bundle_count":14,"receipt":"release-evidence/april-content/weekly/2027-W15.json"}
Copy-paste jq one-liners
Schema + latch
jq -e '.schema == "april_content_update_receipt_v1"
and .april_content_update_weekly_ok == true' \
release-evidence/april-content/weekly/2027-W15.json
Capstone pointer
jq -e '.capstone_pointer.april_content_update_allowed == true' \
release-evidence/april-content/weekly/2027-W15.json
Catalog hash changed honestly
jq -e '
any(.catalog_row_diff[]; .field == "catalog_sha256")
and (.snapshot.catalog_sha256 | length) > 10
' release-evidence/april-content/weekly/2027-W15.json
Diff vs prior jsonl week
PREV=$(jq -s '.[-2].catalog_sha256' release-evidence/april-content/april_content_update_weekly_log.jsonl)
CUR=$(jq -s '.[-1].catalog_sha256' release-evidence/april-content/april_content_update_weekly_log.jsonl)
echo "prev=$PREV cur=$CUR"
test "$PREV" != "$CUR" && echo "catalog changed" || echo "catalog unchanged—confirm intentional freeze"
Count weeks since authorize
jq -s 'length' release-evidence/april-content/april_content_update_weekly_log.jsonl
Fail if RemoteLoadPath drifted silently
jq -e '
all(.catalog_row_diff[]
| select(.field == "remote_load_path");
.delta == "unchanged" or .delta == "documented_path_move")
' release-evidence/april-content/weekly/2027-W15.json
verify_april_content_update.sh
#!/usr/bin/env bash
set -euo pipefail
REC="${1:?weekly april_content_update_receipt_v1.json}"
LOG="${2:-release-evidence/april-content/april_content_update_weekly_log.jsonl}"
jq -e '.schema == "april_content_update_receipt_v1"' "$REC" || exit 1
jq -e '.capstone_pointer.april_content_update_allowed == true' "$REC" || exit 2
jq -e '(.snapshot.catalog_sha256 | length) > 10' "$REC" || exit 3
jq -e '(.snapshot.content_sha256 | length) > 10' "$REC" || exit 4
for g in J1 J2 J3 J4 J5 J6; do
jq -e --arg g "$g" '.gates[$g] == "GREEN"' "$REC" || exit 5
done
jq -e '.april_content_update_weekly_ok == true' "$REC" || exit 6
test -s "$LOG" || exit 7
echo "april_content_update weekly verify: OK"
BUILD_RECEIPT root rows
{
"april_content_update_allowed": true,
"warm_catalog_ok": true,
"april_content_update_weekly_ok": true,
"april_content_update_weekly_receipt": "release-evidence/april-content/weekly/2027-W15.json"
}
Facilitator weekly stand-up (three minutes)
## April content-update weekly — {iso_week}
- catalog_sha256: {short} → {short} ({unchanged|changed})
- content_sha256: {short} → {short}
- remote_load_path: {unchanged|MOVED—need orphan check}
- bundle_count: {n} ({delta})
- warm_pointer: GREEN / waived
- orphan_recovery_ok: {true|false|n/a}
- verify_april_content_update.sh: exit {0}
Paste into #content-update every Monday before Sale ops stand-ups reuse last week's hashes as gospel.
Worked example — W14 → W15 (synthetic)
| Field | W14 | W15 | Delta |
|---|---|---|---|
| catalog_sha256 | aaa111 | ccc333 | new_catalog_build |
| content_sha256 | bbb222 | ddd444 | new_content_build |
| remote_load_path | same | same | unchanged |
| bundle_count | 12 | 14 | +2 |
| orphan_recovery_ok | true | true | unchanged |
Read: Expected content ship. J5 GREEN because diffs list both hashes. If catalog changed but catalog_row_diff empty → J5 RED (silent swap).
RED / YELLOW / GREEN routing
| Signal | Route |
|---|---|
| J2 RED | Capstone not latched—run Friday March capstone |
| J3 RED (week 2+) | Missing prior week line—backfill jsonl before claiming Sale readiness |
| J4 RED | Empty hashes—re-export ServerData; re-run warm evening if first April week |
| J5 RED | Silent hash change—open PATCH exception or redo diff honesty |
| Path moved | Run orphan recovery before GREEN |
| March script still green | Stop—wrong schema for April |
CI cron sketch
on:
schedule:
- cron: "0 9 * * 1"
jobs:
april-weekly-catalog:
if: github.ref == 'refs/heads/content-update-2027-04'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash scripts/verify_april_content_update.sh release-evidence/april-content/weekly/$(date -u +%G-W%V).json
- run: jq -e '.april_content_update_weekly_ok == true' release-evidence/BUILD_RECEIPT.json
Adjust week filename convention to your studio ISO week helper—do not invent Valve weeks.
Common mistakes
Reusing March sprint verify script — Schema mismatch; false GREEN.
Weekly freeze without a log line — J3 fails next week.
Diffing BUILD_RECEIPT MERGE columns in April — Wrong surface.
Warm ok forever — Weekly still required when content rebuilds.
Ignoring path moves — Orphans return (case study).
Hand-typing hashes — Pipe from sha256sum / warm receipt.
Skipping facilitator paste — CI green, humans unaware.
Week-1 bootstrap (no prior jsonl)
The first ISO week after april_content_update_allowed has no prior April catalog line. Do not fake a March sprint row as before.
| Step | Action |
|---|---|
| 1 | Copy catalog_sha256 / content_sha256 from the warm catalog receipt into both before and after if no rebuild shipped |
| 2 | Set catalog_row_diff[].delta to bootstrap for every field |
| 3 | Put "bootstrap": true in receipt notes and gates.J3: "GREEN" with j3_waiver: "week1_no_prior_april_line" |
| 4 | Append the first jsonl line anyway—week 2 J3 needs it |
| 5 | Never set J3 GREEN empty without that waiver text |
Beginner check: Week 1 without a jsonl line causes week 2 verify to fail even if hashes look fine in Slack.
Piping hashes from ServerData (no hand typing)
# Example: pin hashes from your Addressables content build output
CATALOG_FILE="ServerData/StandaloneWindows64/catalog_2027_04_15.hash"
# Or the .json catalog next to bundles—use your studio convention
sha256sum "$CATALOG_FILE" | awk '{print $1}' | tee /tmp/catalog.sha
# Content: choose one required bundle named in warm smoke, or a lockfile hash
sha256sum "ServerData/StandaloneWindows64/your_group_bundle.bundle" | awk '{print $1}' | tee /tmp/content.sha
jq -n --arg c "$(cat /tmp/catalog.sha)" --arg b "$(cat /tmp/content.sha)" \
'{catalog_sha256:("sha256:"+$c), content_sha256:("sha256:"+$b)}'
Paste into snapshot and catalog_row_diff only after these values exist on disk. Hand-typed hex is how Sale week inherits fiction.
Intentional freeze week (hashes unchanged)
Some weeks ship features without a remote content rebuild. Still file a weekly receipt:
"catalog_row_diff": [
{"field": "catalog_sha256", "before": "sha256:ccc333…", "after": "sha256:ccc333…", "delta": "unchanged"},
{"field": "content_sha256", "before": "sha256:ddd444…", "after": "sha256:ddd444…", "delta": "unchanged"},
{"field": "remote_load_path", "before": "https://cdn.example.com/addressables/april-2027/", "after": "https://cdn.example.com/addressables/april-2027/", "delta": "unchanged"}
],
"notes": "Intentional freeze—engineering shipped client-only; remote catalog not rebuilt"
Producer rule: Freeze weeks with empty receipts look like forgotten rituals. A documented unchanged week is GREEN; silence is RED next Monday.
When PATH moves mid-April
If remote_load_path changes:
- Mark delta
documented_path_moveand link ticket id innotes. - Re-run warm catalog A3–A6 against the new URL.
- Run orphan recovery against the old prefix.
- Do not mark J6 GREEN until R3 purge proves old URLs dead.
Prevention for content-update seasons
- Pin
verify_april_content_update.shthe same week capstone latches. - Archive March sprint verify scripts under
legacy/so CI cannot pick the wrong one. - Teach facilitators the three-minute paste before Sale ops meetings.
- Feed weekly lines into forward Thursday content-update review without renaming schemas.
- Keep orphan recovery optional but path-move mandatory.
- Never merge April catalog ok into
march_post_fest_sprint_weekly_ok. - Rehearse week-1 bootstrap once in a dry-run branch before the first live April Monday.
Relationship to forward Thursday content-update review
Forward blog #11 (Thursday content-update BUILD_RECEIPT row review after Wednesday warm smoke) consumes this weekly trail the way Friday March capstone consumed March sprint jsonl. Keep schemas separate:
| Day | Artifact | Question answered |
|---|---|---|
| Monday | This weekly catalog jq | Did remote catalog identity drift since last week? |
| Wednesday | Warm smoke (cousin) | Does the latest candidate still load for a player? |
| Thursday | Forward #11 row review | May we promote / setlive content-update evidence? |
Monday without a jsonl line makes Thursday a guessing game. Thursday without Monday makes promote decisions argue anecdotes.
Outbound references
- jq manual — filters and
-e - Unity Addressables documentation — catalog / content builds
- Steamworks documentation — when content weeks collide with store ops
Key takeaways
- After
april_content_update_allowed, weekly jq must track catalog identity—not March sprint columns. - Use
april_content_update_receipt_v1.json+april_content_update_weekly_log.jsonl. - Gates J1–J6 on the April schema (distinct from March sprint J gates).
- Pointers: capstone + warm catalog (not February closeout).
catalog_row_diff[]must list hash changes honestly—J5.- Pair March sprint jq as cousin cadence only.
- Pair warm catalog for first evening proof.
- Pair orphan recovery when paths or ghosts drift.
verify_april_content_update.shfail-closes empty hashes.- Facilitator three-minute paste beats Slack archaeology.
- Guide #50 / Course 288 forward for step/lesson forms.
- Forward #11 Thursday content-update review consumes this trail.
- Do not append to March jsonl after April authorize.
- Summer Sale claims need current-week J6 GREEN—not last month's warm evening alone.
FAQ
Can we keep using March sprint weekly after capstone?
No—wrong fields. Archive March jsonl; start April catalog log.
Is warm catalog enough for Sale week?
No—warm is candidate evening; weekly diffs catch rebuild drift.
Same J letters as March?
Yes, letter prefix reused; schema string disambiguates. Never mix verify scripts.
What if no content shipped this week?
Still file a line with delta: unchanged on hashes—proves freeze honesty.
Where do orphans fit?
If path moves or bundle_count drops oddly, run orphan recovery before J6.
How does Thursday row review differ?
Thursday content-update row review is the promote ritual; this is Monday weekly catalog identity. Run both: Monday proves hashes, Thursday proves content_update_promote_allowed.
What if Sale week and content week collide?
Still file Monday catalog jq first—Sale store rituals (store response, sticker pass) do not replace catalog identity.
Related GamineAI reads
- jq March post-fest sprint weekly BUILD_RECEIPT row diff
- Friday March Capstone Closeout Before April Content Update
- Your First April Content Update Addressables Warm Catalog Receipt
- We Recovered a Remote Catalog Orphan After Warm Catalog Passed
- Stop Shipping Content Updates Without a Numbered PATCH Exception List — PATCH-00N when J5 sees a silent hash bump
- Thursday Content Update BUILD_RECEIPT Row Review After Warm Catalog — promote latch after Wednesday warm
- Addressables Remote Catalog Drift Validation Loop
- Thursday BUILD_RECEIPT Row Review Ritual — fest cousin
- jq February fest live ops hourly — hourly cousin, wrong for April
- Forward: Guide #50; Course 288
Closing
March weekly dies at the capstone latch—April–June need catalog hash diffs, warm pointers, and a dedicated jsonl. File april_content_update_receipt_v1.json each ISO week, run verify_april_content_update.sh, bootstrap week 1 honestly, document freeze weeks as unchanged, and keep Sale week honest with paths—not folklore from a GREEN warm evening three builds ago. When J5 fires on a silent hash, file PATCH-00N before the next CDN publish. Before Sale CDN promote, run Thursday content-update row review.