Lesson 257: Unity Addressables jq Audit Receipt on BUILD_RECEIPT (2026)

Direct answer: Before October fest Addressables strip PRs merge, promote addressables_audit_jq_receipt_v1.json proving address_inventory_v1.json includes an optional groups[] array (even when empty), CI jq -e 'has("groups")' passes, and inventory keys crosswalk to 7-day key audit K1—distinct from Lesson 219 (addressables_fest_string_table_receipt after strip) and blog addressables_key_audit_receipt_v1 (seven-day calendar). Pair the Addressables jq optional groups preflight (Guide #20).

Lesson hero for Unity Addressables jq audit receipt

Why this matters now (October fest content-update CI)

October 2026 teams pass K1 inventory Monday then merge strip PRs Tuesday—GitHub Actions runs jq on address_inventory_v1.json and fails when the file has keys[] only with no groups field. Engineers “fix” CI by deleting the jq step instead of adding schema—257 files addressables_audit_jq_receipt_v1.json so BUILD_RECEIPT addressables_audit_jq_ok blocks promotion when optional groups is omitted. Invalid Key help is reactive triage; this lesson is inventory schema + CI guard before strip.

The Addressables jq preflight is the ninety-second gate—257 is the BUILD_RECEIPT milestone.

Beginner path (inventory schema → jq → receipt)

Step Action Success check
1 Complete challenge K1 address_inventory_v1.json Keys listed
2 Add groups[] array (can be empty) J2 jq pass
3 Document group membership per key J3 crosswalk
4 Wire CI jq -e 'has("groups")' J4 fail-closed
5 File receipt + BUILD_RECEIPT addressables_audit_jq_ok: true

Time: ~50 minutes first October strip week; ~10 minutes when CI template exists.

Developer path (gates J1–J6)

Gate Check Fail when
J1 address_inventory_v1.json exists K1 skipped
J2 has("groups") jq guard Field omitted entirely
J3 groups[] schema note committed Undocumented optional array
J4 Each key maps to a group name Orphan keys without group
J5 CI fails if groups removed jq step deleted to green CI
J6 Receipt + BUILD_RECEIPT Promote before J4 GREEN

J1 — cousin receipt crosswalk

Field Cousin (blog K7) Cousin (219) This lesson (257)
Schema addressables_key_audit_receipt_v1 addressables_fest_string_table_receipt_v1 addressables_audit_jq_receipt_v1
Scope Seven-day audit calendar Post-strip String Tables Inventory JSON + jq CI guard
Path release-evidence/unity/addressables-audit-week/ release-evidence/localization/ release-evidence/unity/addressables-jq/

Do not merge schemas—reference paths in cousin_receipts only.

address_inventory_v1.json (groups required)

{
  "schema": "address_inventory_v1",
  "build_label": "october-fest-2026-rc2",
  "groups": [
    { "name": "Localization_Local", "strip_candidate": false },
    { "name": "fest_optional", "strip_candidate": true }
  ],
  "keys": [
    {
      "key": "UI/MainMenu",
      "source": "MenuController.cs:42",
      "type": "address",
      "group": "Localization_Local"
    }
  ],
  "orphan_literals": []
}

Schema note: groups is required key, may be empty array []—CI distinguishes “no optional groups field” from “zero groups listed.”

J2 — jq guards (CI)

# Fail closed if groups key missing (J2)
jq -e 'has("groups")' address_inventory_v1.json

# Optional: enforce array type (J3)
jq -e '.groups | type == "array"' address_inventory_v1.json

# Optional: every key.group exists in groups[].name (J4)
jq -e '
  . as $inv |
  ($inv.groups | map(.name)) as $names |
  all($inv.keys[]; .group == null or (.group | IN($names[])))
' address_inventory_v1.json

GitHub Actions sketch:

- name: Addressables inventory jq guard
  run: |
    test -f address_inventory_v1.json
    jq -e 'has("groups")' address_inventory_v1.json
    jq -e '.groups | type == "array"' address_inventory_v1.json

addressables_audit_jq_receipt_v1.json

{
  "schema": "addressables_audit_jq_receipt_v1",
  "build_label": "october-fest-2026-rc2",
  "inventory_path": "release-evidence/unity/addressables-jq/address_inventory_v1.json",
  "inventory_sha256": "aa11…",
  "jq_guards": [
    "has(groups)",
    "groups_is_array",
    "key_group_crosswalk"
  ],
  "ci_workflow": ".github/workflows/addressables-inventory-jq.yml",
  "cousin_receipts": {
    "key_audit_week": "release-evidence/unity/addressables-audit-week/addressables_key_audit_receipt_v1.json",
    "fest_string_table": "release-evidence/localization/ADDRESSABLES_FEST_STRING_TABLE_RECEIPT.json"
  },
  "gates": {
    "J1_inventory": "pass",
    "J2_has_groups": "pass",
    "J3_schema_note": "pass",
    "J4_key_group_crosswalk": "pass",
    "J5_ci_fail_closed": "pass",
    "J6_build_receipt": "pass"
  },
  "addressables_audit_jq_ok": true,
  "content_update_promotion_allowed": true
}

Pin under release-evidence/unity/addressables-jq/ADDRESSABLES_AUDIT_JQ_RECEIPT.json.

BUILD_RECEIPT row (J6)

Column Pass when
addressables_audit_jq addressables_audit_jq_ok: true
addressables_key_audit Cousin blog K7 independent column
string_table_receipt Cousin Lessons 202/219 independent
ALTER TABLE release_publish_gate ADD COLUMN IF NOT EXISTS
  addressables_audit_jq_blocked BOOLEAN NOT NULL DEFAULT false;

Thursday row reviewAddressables jq audit line: has(groups) Y/N.

Key takeaways

  1. groups: [] is valid—missing groups key is not (J2).
  2. Do not delete jq CI to green builds—fix inventory (J5).
  3. 7-day challenge K1 feeds J1—run challenge before strip PR.
  4. Lesson 219 after strip—257 before merge.
  5. Localization_Local preflight — tables lane.
  6. Invalid Key help — runtime triage cousin.
  7. Cousin: Lesson 258 OBS uniform replay—parallel playtest ingest column.
  8. Lesson 256 — parallel localization ingest column.
  9. October capstone 265 wires 254–264 including this row.
  10. Top 20 receipts hub — jq audit row in fest→public map.

Common mistakes

  • Omitting groups because “we have no optional groups”—use groups: [] (J2).
  • Replacing jq guard with Python script that silently passes missing field (J5).
  • Filing 219 while inventory jq still RED—strip vs schema are different gates.
  • Merging addressables_audit_jq_receipt into addressables_key_audit_receipt.
  • Skipping K1 keys—empty groups with empty keys fails J1 purpose.

Troubleshooting

Symptom Lane
CI jq fails on has("groups") Add "groups": [] or populate groups
jq passes, InvalidKey at runtime Invalid Key help
Tables missing post-strip Lesson 219
Key/group mismatch J4 crosswalk jq
Weblate strings wrong Lesson 256

Mini exercise (40 minutes)

  1. Start from K1 inventory without groups—confirm jq fail.
  2. Add "groups": []—confirm J2 pass.
  3. Add one group + key crosswalk—run J4 jq.
  4. File receipt; BUILD_RECEIPT GREEN.

Continuity — October–Q4 2026 fest ops truth (254–265)

Lesson Receipt focus
256 Construct Weblate CSV UTF-8
257 (this) Unity Addressables jq inventory audit
258 OBS uniform replay fragments
265 October ops capstone (queued)

Previous: Lesson 256 — Construct Weblate CSV UTF-8 handoff
Next: Lesson 259 — Bevy menu UI flush (queued)

FAQ

Same as the 7-day challenge?
Challenge owns K1–K7 calendar; 257 owns jq has("groups") BUILD_RECEIPT column.

Same as Lesson 219?
219 = String Tables after strip; 257 = inventory schema before strip.

Empty groups array OK?
Yes—missing groups key is not.

Need jq on Windows agents?
Install jq in CI image or use container step—document in receipt ci_workflow.


October strip PRs fail CI for the wrong reason when groups vanishes from inventory—add the field, guard with jq, crosswalk keys, then addressables_audit_jq_ok before content-update promotion.