Skip to content

culture(germany): migrate hofstede_bag -> khai_lexicon (v1 -> v2 schema)#567

Merged
ChBrain merged 2 commits into
culture/releasefrom
culture/germany
May 27, 2026
Merged

culture(germany): migrate hofstede_bag -> khai_lexicon (v1 -> v2 schema)#567
ChBrain merged 2 commits into
culture/releasefrom
culture/germany

Conversation

@ChBrain

@ChBrain ChBrain commented May 27, 2026

Copy link
Copy Markdown
Owner

First country migration from the v1 hofstede_bag.yaml schema to the v2 khai_lexicon.yaml schema. Framework unchanged (Hofstede 6D, ±5 band). Sets the pattern for Austria, Switzerland, and the other 11 unmigrated cultures.

What changed

Before After
regions/europe/germany/hofstede_bag.yaml khai_lexicon.yaml
regions/europe/germany/hofstede_decisions.md khai_lexicon_decisions.md
culture_german_position.md frontmatter: hofstede: aggregate markers: aggregate

Schema deltas in the YAML

v1 v2
country: germany + parent: null subject: germany + region: europe + subregion: germany
hofstede_scores: marker_scores:
khai_lexicon_version: 1, marker_set: hofstede

The denylist and the six bags (PDI / IDV / UAI / MAS / LTO / IND, each with high/low) carry over verbatim. The framework calls Hofstede one possible marker_set: now so other measurement frameworks can plug into the same lexicon shape later, but the dimension semantics and the scoring scale are unchanged.

Scores

Unchanged. Identical to data/hofstede_scores.json (the fixed target):

PDI 35 · IDV 67 · UAI 65 · MAS 66 · LTO 83 · IND 40

Score-validity re-check

Per the brownfield contract: touching culture_german_position.md (frontmatter swap) triggers a re-read of the position file against the declared marker_scores. The check ran via test_marker_derived.py::test_derived_within_tolerance[germany] and passes — the position file's current voice still lands within ±5 on every dimension. Outcome recorded in khai_lexicon_decisions.md under "v1 -> v2 schema migration".

No score adjustments were needed. Had any dimension fallen out of the ±5 band, the content would have been adjusted to hit the fixed target — never the other way around.

Verification

  • python tests/branch_scope.py advise → all three files route to culture/germany (base culture/release) ✅
  • python tests/validate_pr_brownfield.py origin/culture/release → "Touched files are migration-current" ✅
  • pytest tests/test_marker_derived.py -k germany → 2/2 pass ✅
  • Pre-commit hook clean, no --no-verify

Unblocks

  • PR culture(europe): bake DACH group membership into member positions #564 (DACH baking on culture/europe): once Austria and Switzerland are migrated the same way, the brownfield R3 gate stops firing on the three DACH position files there.
  • Establishes the migration template for the 11 other v1 cultures (austria, switzerland, denmark, france, netherlands, poland, spain, japan, singapore, australia, mexico, united_states, nigeria).

Follow-up not in this PR

Several test/script files still carry the hofstede_* filename even though the abstraction has moved to marker_*. They should be renamed in a governance PR:

  • scripts/update_hofstede_readme.py
  • tests/test_hofstede_bag_loader.py, test_hofstede_bag_fork.py, test_hofstede_bag_locked.py, test_hofstede_bag_quality.py, test_hofstede_bag_shape.py, test_hofstede_score_home.py, test_hofstede_reference.py, test_hofstede_structure.py, test_update_hofstede_readme.py

tests/test_marker_derived.py is the precedent: same logic, abstract name, drives the ±5 band check this PR depends on.

Ref: #564, #545


Generated by Claude Code

Mechanical rename, framework unchanged (Hofstede 6D, ±5 band). The
new schema names Hofstede as one possible marker_set: so other
measurement frameworks can plug into the same lexicon shape later.

Files:
- hofstede_bag.yaml          -> khai_lexicon.yaml
- hofstede_decisions.md      -> khai_lexicon_decisions.md
- culture_german_position.md frontmatter: hofstede: aggregate
                                       -> markers: aggregate

Schema deltas in the YAML:
- country: germany + parent: null     -> subject: germany + region: europe
                                         + subregion: germany
- hofstede_scores:                    -> marker_scores:
- new keys: khai_lexicon_version: 1, marker_set: hofstede

Scores unchanged: PDI 35, IDV 67, UAI 65, MAS 66, LTO 83, IND 40.

Brownfield score-validity check (per the "if you touch, you verify"
contract): re-read culture_german_position.md against marker_scores.
test_marker_derived.py::test_derived_within_tolerance[germany] passes
-- the position file's voice still hits target within ±5 across all
six dimensions. Outcome recorded in khai_lexicon_decisions.md under
"v1 -> v2 schema migration".

Unblocks PR #564 (DACH baking on culture/europe): once Austria and
Switzerland are migrated the same way, the brownfield R3 gate stops
firing on the three position files there.
@github-actions

Copy link
Copy Markdown

khai_tests.review on this PR

germany

khai_tests.review prose-naturalness

culture_german_position.md -- prose naturalness -- flagged

  • "Die Frage, immer mit Disziplin und Zurückhaltung gestellt." - This sentence is fragmented and lacks a main verb, making it sound unnatural.
  • "Zuerst, aber nicht leichtfertig." - This is a sentence fragment and does not form a complete thought.
  • "Nicht als Höflichkeit: als Pflichterfüllung." - This is another fragment that lacks a main verb and does not read as a complete sentence.
  • "Als Recht, gerahmt durch Verantwortungsgefühl." - This phrase is also a fragment and does not convey a complete idea.
  • "Verdienst durch Leistung, nicht Konkurrenz um Glanz." - This is a fragment and lacks a main verb, making it sound incomplete.
  • "Gleichberechtigung in der Befragung, wenn alle sich an Regeln halten." - This sentence is awkwardly structured and could be more fluid.
  • "Eigeninitiative: Dein eigenes Denken ist Werkzeug." - This is a fragment and does not form a complete thought.
  • "Aber auch: Entspannung." - This is a sentence fragment and lacks a main verb.
  • "Lebensfreude, nicht ständig, aber echt wenn sie kommt." - This sentence is awkwardly structured and could be more fluid.
  • "Gelassenheit, wenn die Pflicht ruht." - This is a fragment and lacks a main verb.
  • "Nicht als Befehl: als Rahmen der Pflicht, mit Prinzipien." - This is a fragment and does not form a complete thought.
  • "Vertrag über Handeln, mit Selbstkontrolle." - This is a fragment and lacks a main verb.
  • "Lehren gelten, nicht zum Brechen gedacht." - This is a fragment and does not convey a complete idea.
  • "Disziplin." - This is a one-word sentence and does not read as a complete thought.
  • "Ordnung." - This is a one-word sentence and does not read as a complete thought.
  • "Genauigkeit und Gründlichkeit als Ausdruck von Respekt." - This is a fragment and lacks a main verb.
  • "Beharrlichkeit statt Hastigkeit." - This is a fragment and does not form a complete thought.
  • "Ausdauer als Maßstab." - This is a fragment and lacks a main verb.
  • "Denke klar." - This is a one-word sentence and does not read as a complete thought.
  • "Handle mit Struktur." - This is a one-word sentence and does not read as a complete thought.
  • "Klarheit: die Fähigkeit, zu sagen: Ich weiß es nicht." - This is awkwardly structured and could be more fluid.
  • "Der Raum für spontane Freude." - This is a fragment and lacks a main verb.
  • "Auf dem Verlust:" - This is a fragment and does not form a complete thought.
  • "Verzweifelte Suche nach Verfahren." - This is a fragment and lacks a main verb.
  • "Erinnern: die Fähigkeit, Struktur aus der Geschichte zu rekonstruieren." - This sentence is awkwardly structured and could be more fluid.

khai_tests.review persona-distinct

german_persona_female_brigitte.md, german_persona_male_christian.md -- persona distinctness -- PASS

khai_tests.review shadow-not-position

german_persona_female_brigitte.md vs culture_german_position.md -- shadow != position -- PASS

khai_tests.review typical-of

german_persona_female_brigitte.md -- typical of Germany culture -- PASS

khai_tests.review shadow-not-position

german_persona_male_christian.md vs culture_german_position.md -- shadow != position -- PASS

khai_tests.review typical-of

german_persona_male_christian.md -- typical of Germany culture -- PASS

khai_tests.review vocab-overlap

culture_german_piece_autobahn.md vs culture_german_position.md -- vocab overlap -- flagged

  • "Freie Fahrt für freie Bürger" - echoes the position's value-word "Autonomie"
  • "Das Auto als Statussymbol auf vier Rädern" - echoes the position's value-word "Statussymbol"
  • "Regelwerk und Tempolimit-Aufhebung in Spannung, beide echt" - echoes the position's value-word "Vorschriftenwerk"
  • "Investition über Jahrzehnte: die Republik baut, wartet, erneuert" - echoes the position's value-word "Investition"
  • "Verkehrswende-Debatten in Berlin; auf der Strecke fährt sie weiter" - echoes the position's value-word "Debatten"
  • "Geschwindigkeit wird Symbol" - echoes the position's value-word "Symbol"
  • "Die Nazis übernehmen die Pläne, propagandieren sie als ihre Erfindung" - echoes the position's value-word "Propaganda"
  • "Die Geschichte hängt am Beton" - echoes the position's value-word "Geschichte"

khai_tests.review vocab-overlap

culture_german_piece_history.md vs culture_german_position.md -- vocab overlap -- flagged

  • "Die Verantwortung gegenüber Vergangenheit als nationale Pflicht." - echoes "Pflicht und Verpflichtung: die wahre Grundlage."
  • "Die Geschichte trägt, weil sie nicht weggewischt wird." - echoes "Ernsthaftigkeit vor Anerkennung."
  • "Die WM-Pokale in der DFB-Zentrale: 1954, 1974, 1990, 2014." - echoes "Verdienst durch Leistung, nicht Konkurrenz um Glanz."
  • "Eine Republik, die ihr Werden vor dem Spiegel hält." - echoes "Eigeninitiative: Dein eigenes Denken ist Werkzeug."
  • "Die Teilung sichtbar im Beton." - echoes "Ordnung. Struktur braucht die Seele nicht, aber die Gesellschaft."
  • "Die Fragmentierung zementiert." - echoes "Langfristigkeit als Standard im Aufbau."
  • "Erinnerungsorte in jeder größeren Stadt: KZ-Gedenkstätten, Stadtmuseen, Stolpersteine." - echoes "Gleichberechtigung in der Befragung, wenn alle sich an Regeln halten."
  • "Die Berliner Mauer als Linie aus Pflastersteinen, sichtbar wo sie nicht mehr steht." - echoes "Beharrlichkeit in Arbeit; Flexibilität in Seele nicht."
  • "Das Bundesverfassungsgericht in Karlsruhe, modern und unornamental." - echoes "Disziplin."
  • "Die Verantwortung gegenüber Vergangenheit als nationale Pflicht." - echoes "Pflicht und Verpflichtung: die wahre Grundlage."
  • "Die Geschichte trägt, weil sie nicht weggewischt wird." - echoes "Ernsthaftigkeit vor Anerkennung."

khai_tests.review vocab-overlap

culture_german_place_berlin.md vs culture_german_position.md -- vocab overlap -- PASS

khai_tests.review vocab-overlap

culture_german_position_language.md vs culture_german_position.md -- vocab overlap -- flagged

  • "Hochdeutsch ist die Sprache der Institution, nicht der Straße" - echoes the position's value-word "Ordnung" (structure)
  • "Die Präzision der Hochsprache ist nicht Stil, sondern Schule" - echoes the position's value-word "Disziplin" (discipline)
  • "Setze den Konjunktiv, wo du nicht weißt" - echoes the position's value-word "Denke klar" (think clearly)
  • "Die Sprache kann nicht alles regeln; die Seele bleibt frei" - echoes the position's value-word "Gelassenheit" (serenity)

khai_tests.review vocab-overlap

culture_german_process_erinnern.md vs culture_german_position.md -- vocab overlap -- PASS


Advisory -- does not block merge. Built on khai_tests.review.

khai-tests==0.1.19 requires every khai file to open with a ## Title
chapter (the "TO pair": Title + Owner). engine/wow position files
already carry it; existing culture position files don't, which fails
khai - Position rules on every PR that modifies one.

Adds:
  ## Title
  German

after the L1 "# Position: German" and before "## Owner".

Verification:
- khai_tests.components.test_khai_position: 6/6 pass
- test_marker_derived.py[germany]: 2/2 pass (text addition does not
  fire any bag word; scores remain in the ±5 band)
- validate_pr_brownfield.py: still clean

The other 13 unmigrated cultures will need the same chapter when they
migrate. Austria and Switzerland get it as part of their migrations
(this PR's pattern).

ChBrain commented May 27, 2026

Copy link
Copy Markdown
Owner Author

CI gap closed — Position rules

khai - Position rules failed because khai-tests==0.1.19 requires every khai file to open with a ## Title chapter (the "TO pair": Title + Owner). engine/wow/position_technicians.md already carries it; existing culture position files don't.

Fix (d22b11d): Added

## Title
German

between the L1 # Position: German and ## Owner in culture_german_position.md.

Verification

Gate Result
khai_tests.components.test_khai_position (the failing one) 6/6 pass ✅
test_marker_derived.py[germany] band check 2/2 pass — text addition doesn't fire any bag word, scores stay in ±5 ✅
validate_pr_brownfield.py still clean ✅

Learning carried to Austria + Switzerland

When their migration PRs land, they get the same chapter (## Title\n<Adjective>\n) added in the same spot. Bake it into the per-country PR scope instead of opening a separate region-spanning cleanup.

Notes for the broader fleet

This pattern (## Title between L1 and ## Owner) needs to land in every culture position file eventually — UK lacks it too, but its PR isn't open, so the position-rules check doesn't fire on it. The remaining 11 unmigrated cultures will get it as part of their own migrations under the same brownfield contract.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown

khai_tests.review on this PR

germany

khai_tests.review prose-naturalness

culture_german_position.md -- prose naturalness -- flagged

  • "Die Frage, immer mit Disziplin und Zurückhaltung gestellt." - This sentence is fragmented and lacks a main verb, making it sound unnatural.
  • "Zuerst, aber nicht leichtfertig." - This is a sentence fragment and does not form a complete thought.
  • "Nicht als Höflichkeit: als Pflichterfüllung." - This is another fragment that lacks a main verb and does not read as a complete sentence.
  • "Als Recht, gerahmt durch Verantwortungsgefühl." - This phrase is also a fragment and does not convey a complete idea.
  • "Verdienst durch Leistung, nicht Konkurrenz um Glanz." - This is a fragment and lacks a main verb, making it sound incomplete.
  • "Gleichberechtigung in der Befragung, wenn alle sich an Regeln halten." - This is a complex sentence but could be clearer; it may sound awkward to a native speaker.
  • "Eigeninitiative: Dein eigenes Denken ist Werkzeug." - This is a fragment and lacks a main verb.
  • "Aber auch: Entspannung." - This is a fragment and does not form a complete thought.
  • "Lebensfreude, nicht ständig, aber echt wenn sie kommt." - This is a fragmented thought and lacks clarity.
  • "Gelassenheit, wenn die Pflicht ruht." - This is another fragment that does not convey a complete idea.
  • "Nicht als Befehl: als Rahmen der Pflicht, mit Prinzipien." - This is a fragment and lacks a main verb.
  • "Vertrag über Handeln, mit Selbstkontrolle." - This is a fragment and does not form a complete thought.
  • "Lehren gelten, nicht zum Brechen gedacht." - This is a fragment and lacks a main verb.
  • "Disziplin." - This is a one-word sentence and does not provide a complete thought.
  • "Ordnung." - This is another one-word sentence that lacks context.
  • "Genauigkeit und Gründlichkeit als Ausdruck von Respekt." - This is a fragment and lacks a main verb.
  • "Beharrlichkeit statt Hastigkeit." - This is a fragment and does not convey a complete idea.
  • "Ausdauer als Maßstab." - This is a fragment and lacks a main verb.
  • "Denke klar." - This is a command and lacks context.
  • "Handle mit Struktur." - This is another command and lacks context.
  • "Klarheit: die Fähigkeit, zu sagen: Ich weiß es nicht." - This is a fragment and does not form a complete thought.
  • "Der Raum für spontane Freude." - This is a fragment and lacks a main verb.
  • "Auf dem Verlust: Verzweifelte Suche nach Verfahren." - This is a fragmented thought and lacks clarity.
  • "Erinnern: die Fähigkeit, Struktur aus der Geschichte zu rekonstruieren." - This is a fragment and lacks a main verb.

khai_tests.review persona-distinct

german_persona_female_brigitte.md, german_persona_male_christian.md -- persona distinctness -- PASS

khai_tests.review shadow-not-position

german_persona_female_brigitte.md vs culture_german_position.md -- shadow != position -- PASS

khai_tests.review typical-of

german_persona_female_brigitte.md -- typical of Germany culture -- PASS

khai_tests.review shadow-not-position

german_persona_male_christian.md vs culture_german_position.md -- shadow != position -- PASS

khai_tests.review typical-of

german_persona_male_christian.md -- typical of Germany culture -- PASS

khai_tests.review vocab-overlap

culture_german_piece_autobahn.md vs culture_german_position.md -- vocab overlap -- PASS

khai_tests.review vocab-overlap

culture_german_piece_history.md vs culture_german_position.md -- vocab overlap -- PASS

khai_tests.review vocab-overlap

culture_german_place_berlin.md vs culture_german_position.md -- vocab overlap -- PASS

khai_tests.review vocab-overlap

culture_german_position_language.md vs culture_german_position.md -- vocab overlap -- flagged

  • "Hochdeutsch ist die Sprache der Institution, nicht der Straße" - echoes the value-word "Ordnung" (structure)
  • "Die Präzision der Hochsprache ist nicht Stil, sondern Schule" - echoes the value-word "Disziplin" (discipline)
  • "Jeder Satz folgt seiner Struktur" - echoes the value-word "Ordnung" (structure)
  • "Setze den Konjunktiv, wo du nicht weißt" - echoes the value-word "Denke klar" (think clearly)
  • "Lass das Wort sagen, was es sagt" - echoes the value-word "Ernsthaftigkeit" (seriousness)
  • "Die Sprache kann nicht alles regeln; die Seele bleibt frei" - echoes the value-word "Gelassenheit" (serenity)

khai_tests.review vocab-overlap

culture_german_process_erinnern.md vs culture_german_position.md -- vocab overlap -- PASS


Advisory -- does not block merge. Built on khai_tests.review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants