governance: ship unified Cultures release manifest (Phase C step 2)#576
Merged
Conversation
Step 2 of the unified-contract rollout. KAIHACKS #274 (step 1) taught the consumer to read groupings from available.json, with a fallback fetch of the legacy groupings.json during the transition. This change teaches the producer to ship the unified shape. What used to be two scripts and two delivered files is now one: scripts/generate_available_json.py produces: { schemaVersion: 1, release: <tag>, downloadBase: <url>, cultures: [...] <-- from data/countries.json groupings: [...] <-- NEW: from groups/*/*_position.md } scripts/generate_groupings.py DELETED .github/workflows/deliver-available-json.yml Drops the "Regenerate groupings.json" step. PR title + body now reference one file (available.json), the unified release manifest, rather than two. Adds an explicit `pip install pyyaml` step (the frontmatter parser was previously pulled in by the now-removed second script's import). Why one file (recap from KAIHACKS #274): Release tag, cultures, and groupings are three concerns of the same release. Splitting them across two files leaves no atomicity guarantee -- a DACH grouping could name a culture id that the cultures[] array does not contain, or the badge could point to a release tag whose cultures the page is not showing. One file. One schema. Atomic versioning. One fetch on the consumer side. What this commit preserves exactly: - Groupings pickup mechanism: walk groups/<dir>/*_position.md, take every file whose YAML frontmatter has `grouping: true`. The id, name, blurb, and members fields project verbatim. id and name fall back to the directory name when unset. Behavior is bit-for- bit identical to the deleted generate_groupings.py. - Producer-side grouping invariants: id pattern ^[a-z0-9_-]+$, unique ids, non-empty members[], non-empty blurb. Same checks, now in check_manifest() alongside the culture invariants. - Culture id regex unchanged (^[a-z0-9-]+$, no underscore). The two regexes are now named _CULTURE_ID_RE and _GROUPING_ID_RE to make the per-shape rule explicit at the call site. Schema compatibility: the unified manifest still validates against available.schema.json on KAIHACKS, because step 1 (#274) added the optional `groupings` field at schemaVersion 1. No bump needed; the addition is additive at v1. Tests: +7 new tests in TestGroupings (clean shape, bad id, underscore id allowed, duplicate id, empty members, empty blurb, empty list is valid). _manifest() helper grew an optional groupings= kwarg (defaults to []), test_top_level_shape() now asserts the field is present. All 24 tests in test_generate_available_json.py pass. branch_scope.py and test_branch_scope.py drop the scripts/generate_groupings.py entry from the governance scope list (the file no longer exists). 259 branch-scope tests pass. Smoke-test against the live tree: python scripts/generate_available_json.py --release v0.99.0 ... -> "wrote 16 cultures and 0 groupings" (0 groupings because the local tree has no groups/ directory yet; the legacy generator also returned 0 -- behavior preserved.) Rollout step left (step 3, after one release cycle proves the unified shape in production): KAIHACKS: drop the legacy fallback fetch from cultures-map.js, delete groupings.json, bump schemaVersion to 2 with `groupings` required. Refs: ChBrain/KAIHACKS#274
This was referenced May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 2 of the unified-contract rollout. KAIHACKS #274 (step 1) taught the consumer to read
groupingsfromavailable.json, with a fallback fetch of the legacygroupings.jsonduring the transition. This change teaches the producer to ship the unified shape.What changed
What used to be two scripts and two delivered files is now one.
scripts/generate_available_json.py— producesavailable.json(cultures + release tag)available.jsonwithcultures[]ANDgroupings[]in one atomic shapescripts/generate_groupings.py— producesgroupings.jsondeliver-available-json.yml— two regen steps, two-file PRpip install pyyamlstep (the frontmatter parser was previously imported transitively via the now-removed second script).What this PR preserves exactly
groups/<dir>/*_position.md, take every file whose YAML frontmatter hasgrouping: true.id,name,blurb,membersproject verbatim.idandnamefall back to the directory name when unset. Bit-for-bit identical to the deletedgenerate_groupings.py.idpattern^[a-z0-9_-]+$, unique ids, non-emptymembers[], non-emptyblurb. Same checks, now incheck_manifest()alongside the culture invariants.^[a-z0-9-]+$, no underscore). The two regexes are now named_CULTURE_ID_REand_GROUPING_ID_REto make the per-shape rule explicit at the call site.Schema compatibility
The unified manifest still validates against
available.schema.jsonon KAIHACKS, because step 1 (#274) added the optionalgroupingsfield atschemaVersion: 1. No bump needed — the addition is additive at v1.Verification
python scripts/generate_available_json.py --release v0.99.0 --out /tmp/u.json→
wrote 16 cultures and 0 groupings(0 because the local tree has nogroups/dir; legacy generator also returned 0, behavior preserved) ✅pytest tests/test_generate_available_json.py→ 24 passed (+7 newTestGroupingstests covering clean shape, bad id, underscore allowed, duplicate id, empty members, empty blurb, empty list valid) ✅pytest tests/test_branch_scope.py→ 259 passed ✅.githooks/pre-commit→ ✅Rollout step left
Step 3 (after one release cycle proves the unified shape in production):
cultures-map.jsgroupings.jsonschemaVersionto 2 withgroupingsrequiredRefs: ChBrain/KAIHACKS#274
Generated by Claude Code