random_name_generator 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4e1b055a45228bf4370e655f590397e940bc716c1c1fe1ef2259c66a3fcd09e
4
- data.tar.gz: 67f9020b9f20969b6d5151a5388ffcab6142b47ebc0cabbeee952dfe711e7599
3
+ metadata.gz: 0e3511685f7df265b945b6254e889eac64d5857309623a5c09f91f309f9fc52d
4
+ data.tar.gz: bc756891b8f9adda7c154aed1b6865f3e4746f6d57ca87c2c01357ea9d9912c4
5
5
  SHA512:
6
- metadata.gz: 1395584c6872c6dfb65da4117f973ec1065c6002d854f550b266546001ffe52b881258718e83eb75f8389073acc30b0fb2963dc1d15216b344d8dfc85ca39532
7
- data.tar.gz: cef21f4dc10098e3d8d132a36baf5674d0029234c62a641861bcc474ea20aab8afaf03a59f2b5285f336cde34323e1e324e44afd9ea5d1ba0596e002c764a9f9
6
+ metadata.gz: dced56da054f6c842dc74cb2ac40baae325b2edea5645494fdadf6f3243259137e89fb32924f50052487c14d4d151944efc5d923ed1bef2698effb7f306c6357
7
+ data.tar.gz: 25b9619caf21f3e0e04561eed930839d2f599564e77ea194c43f76944a191220732851f8e6e961cf2da8a8568f9f5102b49751c1e866c021a224ed8fb34acd0c
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: lang-gen
3
+ description: Generate a new random_name_generator language from a free-text theme (e.g. "german curse words") — assembles flagged pre/mid/sur syllable collections, registers the File constant, adds a smoke spec and README entry, and samples names to verify. Use when asked to create, generate, or add a new language, dialect, or syllable file for the name generator.
4
+ ---
5
+
6
+ # lang-gen
7
+
8
+ Turn a free-text theme into a fully integrated `random_name_generator`
9
+ language file. This workflow is written to be model-agnostic: any assistant
10
+ that can edit files and run commands can follow it.
11
+
12
+ ## The language-file DSL
13
+
14
+ Authoritative source: `lib/random_name_generator/syllable.rb`. Each line of a
15
+ language `.txt` is one syllable:
16
+
17
+ - Leading `-` → **prefix** (pre) bucket — a name beginning.
18
+ - Leading `+` → **suffix** (sur) bucket — a name ending.
19
+ - No sign → **middle** (mid) bucket — an interior fragment.
20
+
21
+ Optional whitespace-separated flags after the syllable constrain adjacency:
22
+
23
+ - `+v` — the NEXT syllable must start with a vowel.
24
+ - `+c` — the NEXT syllable must start with a consonant.
25
+ - `-v` — THIS syllable may only follow one ending in a vowel.
26
+ - `-c` — THIS syllable may only follow one ending in a consonant.
27
+
28
+ A name needs all three buckets non-empty. `Generator#compose` picks a prefix,
29
+ fills with middles, ends with a suffix, honoring the flags.
30
+
31
+ ## Workflow
32
+
33
+ Follow these steps in order. Do not skip verification.
34
+
35
+ ### 1. Parse the theme and derive names
36
+
37
+ From the argument string derive and then **show the user for confirmation**:
38
+
39
+ - **slug** — concise kebab-case, 1–2 meaningful words, drop filler ("words",
40
+ "generator", articles). `german curse words` → `german-curse`.
41
+ - **constant** — SCREAMING_SNAKE of the slug. `german-curse` → `GERMAN_CURSE`.
42
+ - **destination** — edgy themes (curse, insult, swear, NSFW, drunk, etc.) →
43
+ `lib/languages/experimental/<slug>.txt`; tame themes →
44
+ `lib/languages/<slug>.txt`.
45
+
46
+ Before writing anything, check for collisions: if the target `.txt` OR the
47
+ constant already exists, STOP and ask the user how to proceed. Never overwrite.
48
+
49
+ ### 2. Author the syllable file (hybrid: seed, then extend)
50
+
51
+ 1. Recall a handful of **real roots** for the theme. (German curses: `schei`,
52
+ `arsch`, `sau`, `verdammt`, `dreck`, `mist`, `depp`, `blöd`, …)
53
+ 2. Slot fragments into buckets: prefixes (`-`) = natural beginnings, middles
54
+ (bare) = connective interiors, suffixes (`+`) = natural endings / intensifiers.
55
+ 3. **Extend** each bucket with same-flavor **invented** syllables until each
56
+ holds ~20–40 entries (match `lib/languages/goblin.txt` scale).
57
+ 4. Add `+v/+c/-v/-c` flags **only where they prevent awkward clusters** — e.g. a
58
+ consonant-final prefix that would collide, or a lone vowel that reads badly
59
+ after another vowel. Most lines carry no flag. Keep it judicious.
60
+
61
+ Write the file to the destination from step 1.
62
+
63
+ ### 3. Register the constant
64
+
65
+ Edit `lib/random_name_generator.rb`. Add, next to the matching group of
66
+ constants (edgy → under the `# Experimental` comment; tame → with the curated
67
+ constants):
68
+
69
+ ```ruby
70
+ CONSTANT_NAME = File.new("#{dirname}/languages/<relative/path>.txt")
71
+ ```
72
+
73
+ Do NOT touch `flip_mode` or `flip_mode_cyrillic` — those arrays are curated.
74
+
75
+ ### 4. Add a smoke spec
76
+
77
+ Add an example to `spec/random_name_generator_spec.rb` following existing
78
+ conventions (see the `with languages` context). It must assert the constant is a
79
+ `File`, its `path` includes the expected filename, and that a `Generator` built
80
+ from it composes a non-empty `String`:
81
+
82
+ ```ruby
83
+ it "when it has a <Theme> language" do
84
+ expect(RandomNameGenerator::CONSTANT_NAME).to be_a(File)
85
+ expect(RandomNameGenerator::CONSTANT_NAME.path).to include("languages/<relative/path>.txt")
86
+ name = RandomNameGenerator::Generator.new(RandomNameGenerator::CONSTANT_NAME).compose
87
+ expect(name).to be_a(String)
88
+ expect(name).not_to be_empty
89
+ end
90
+ ```
91
+
92
+ ### 5. Add a README entry
93
+
94
+ Add the new language to `README.md`. Edgy/experimental languages go under a
95
+ short "Experimental languages" note; tame ones join the curated list. Link to
96
+ the file, matching how the curated four are listed.
97
+
98
+ ### 6. Verify — parse-check then sample
99
+
100
+ - **Parse-check:** confirm every line is a valid syllable and all three buckets
101
+ are non-empty. Fastest via the gem:
102
+
103
+ ```bash
104
+ bundle exec ruby -Ilib -rrandom_name_generator -e '
105
+ g = RandomNameGenerator::Generator.new(RandomNameGenerator::CONSTANT_NAME)
106
+ abort "empty pre" if g.pre_syllables.empty?
107
+ abort "empty mid" if g.mid_syllables.empty?
108
+ abort "empty sur" if g.sur_syllables.empty?
109
+ puts "buckets OK: #{g.pre_syllables.size}/#{g.mid_syllables.size}/#{g.sur_syllables.size}"
110
+ '
111
+ ```
112
+
113
+ - **Sample:** print ~10 composed names for the user to eyeball:
114
+
115
+ ```bash
116
+ bundle exec ruby -Ilib -rrandom_name_generator -e '
117
+ g = RandomNameGenerator::Generator.new(RandomNameGenerator::CONSTANT_NAME)
118
+ 10.times { puts g.compose }
119
+ '
120
+ ```
121
+
122
+ - **Run the spec:** `bundle exec rspec spec/random_name_generator_spec.rb`
123
+
124
+ If names look broken or monotonous, iterate on the `.txt` (more variety, better
125
+ flags) and re-sample before finishing.
126
+
127
+ ### 7. Hand off the commit
128
+
129
+ Git is manual in this workflow. Do NOT run git yourself. Surface the exact
130
+ command for the user:
131
+
132
+ ```bash
133
+ git add lib/languages README.md lib/random_name_generator.rb spec/random_name_generator_spec.rb && git commit -m "Add <Theme> language via /lang-gen"
134
+ ```
135
+
136
+ ## Guardrails
137
+
138
+ - Never overwrite an existing language file or constant without confirmation.
139
+ - Never run state-changing git commands — always suggest them.
140
+ - Keep bucket sizes and flag style consistent with existing `lib/languages/*.txt`.
@@ -28,7 +28,7 @@ jobs:
28
28
  - ruby-version: head
29
29
  allow-failure: true
30
30
  steps:
31
- - uses: actions/checkout@v4
31
+ - uses: actions/checkout@v5
32
32
  - name: Set up Ruby
33
33
  uses: ruby/setup-ruby@v1
34
34
  with:
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- random_name_generator (4.0.0)
4
+ random_name_generator (4.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -30,11 +30,26 @@ gem 'random_name_generator'
30
30
 
31
31
  And then execute:
32
32
 
33
- $❯ bundle install
33
+ `$❯ bundle install`
34
34
 
35
35
  Or install it yourself as:
36
36
 
37
- $❯ gem install random_name_generator
37
+ `$❯ gem install random_name_generator`
38
+
39
+ `RandomNameGenerator` also comes with a command line interface which will
40
+ generate a first and last name for you:
41
+
42
+ ```shell
43
+ $> exe/random_name_generator [-egrkfcxdß?]
44
+ ```
45
+
46
+ You can also install it so that it's instantly available to you:
47
+
48
+ ```shell
49
+ $> bundle exec rake install
50
+ $> random_name_generator --german-curse
51
+ Dummkopfischpopelsepp Schnoddmistmann
52
+ ```
38
53
 
39
54
  ## Usage
40
55
 
@@ -42,8 +57,9 @@ RandomNameGenerator comes with several styles of syllable files:
42
57
  [Elven](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/elven.txt),
43
58
  [Fantasy](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/fantasy.txt),
44
59
  [Goblin](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/goblin.txt),
60
+ [Roman](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/roman.txt),
45
61
  and
46
- [Roman](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/roman.txt).
62
+ [Klingon](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/klingon.txt).
47
63
  By default it uses Fantasy. Instantiate RandomNameGenerator and then
48
64
  call compose on the object to generate a random name. If you don't pass
49
65
  in the number of syllables you want for your name to compose, it will
@@ -79,15 +95,16 @@ You can also pass in your own syllable files. See
79
95
  [Syllable.rb](https://github.com/folkengine/random_name_generator/blob/master/lib/random_name_generator/syllable.rb)
80
96
  for the required specification.
81
97
 
82
- RandomNameGenerator also comes with a command line interface which will
83
- generate a first and last name for you:
84
-
85
- ```
86
- bin/random_name_generator [-efgr?]
87
- ```
98
+ ### Experimental languages
88
99
 
89
- Add the gem's bin directory to you path in order to have instant access
90
- to RandomNameGenerator.
100
+ Edgier, less curated syllable sets live under `lib/languages/experimental/`
101
+ and are opt-in via their own constants:
102
+ [Curse](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/experimental/curse.txt)
103
+ (`RandomNameGenerator::CURSE`),
104
+ [Demonic](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/experimental/demonic.txt)
105
+ (`RandomNameGenerator::DEMONIC`), and
106
+ [German Curse](https://github.com/folkengine/random_name_generator/blob/master/lib/languages/experimental/german-curse.txt)
107
+ (`RandomNameGenerator::GERMAN_CURSE`).
91
108
 
92
109
  ## Porting and Refactoring Notes
93
110
 
@@ -98,7 +115,7 @@ syllable, greatly simplifying the Random Name Generator code.
98
115
  Part of the reason for working on this gem was to work on the following
99
116
  goals to improve my Ruby craft:
100
117
 
101
- * Code confidently in the spirit of Advi Grimm's
118
+ * Code confidently in the spirit of Avdi Grimm's
102
119
  [Confident Ruby](http://www.confidentruby.com/).
103
120
  * ~~Use
104
121
  [Travis-CI](https://travis-ci.org/folkengine/random_name_generator)
@@ -130,6 +147,44 @@ call `$❯ rake reek`
130
147
  Bug reports and pull requests are welcome on GitHub at
131
148
  https://github.com/folkengine/random_name_generator.
132
149
 
150
+ ## Skills
151
+
152
+ This ships with a skill designed to work with [Claude Code](https://claude.com/claude-code)
153
+ and other LLMs under `.claude/skills/`.
154
+
155
+ - [lang-gen](.claude/skills/lang-gen/SKILL.md) — Generate a new random_name_generator language from a free-text theme (e.g. "german curse words") — assembles flagged pre/mid/sur syllable collections, registers the File constant, adds a smoke spec and README entry, and samples names to verify.
156
+
157
+ There is also [a text version](docs/superpowers/specs/2026-07-19-lang-gen-portable-prompt.md) of the prompt that can be pasted into an LLM.
158
+
159
+ ### lang-gen
160
+
161
+ Adding a language by hand means writing a `.txt` of prefix/middle/suffix
162
+ syllables, wiring up a `File` constant, adding a spec, and documenting it.
163
+ `lang-gen` does the whole flow from a plain-English theme.
164
+
165
+ Invoke it from Claude Code with the theme as the argument:
166
+
167
+ ```
168
+ /lang-gen Klingon words of joy
169
+ ```
170
+
171
+ This will:
172
+
173
+ 1. Derive a **slug** (`klingon-joy`), **constant** (`KLINGON_JOY`), and
174
+ destination; edgy themes land in `lib/languages/experimental/`, tame
175
+ ones in `lib/languages/`; and confirm before writing.
176
+ 2. Author the syllable file, seeding real roots for the theme and extending
177
+ each of the three buckets (prefix `-`, middle, suffix `+`) with same-flavor
178
+ syllables, adding `+v`/`+c`/`-v`/`-c` adjacency flags only where needed.
179
+ 3. Register the `File` constant in `lib/random_name_generator.rb`.
180
+ 4. Add a smoke spec to `spec/random_name_generator_spec.rb`.
181
+ 5. Add a README entry linking the new language.
182
+ 6. Verify that all three buckets are non-empty, then sample
183
+ composed names so you can eyeball the result.
184
+
185
+ The experimental [German Curse](lib/languages/experimental/german-curse.txt)
186
+ language was generated this way.
187
+
133
188
  ## License
134
189
 
135
190
  The gem is available as open source under the terms of the
@@ -0,0 +1,320 @@
1
+ # /lang-gen Skill Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Build a project-local `/lang-gen` skill that turns a free-text theme (e.g. "german curse words") into a fully integrated `random_name_generator` language.
6
+
7
+ **Architecture:** The deliverable is a single prose skill file, `.claude/skills/lang-gen/SKILL.md`, that instructs Claude through a fixed workflow: parse the theme → derive slug/constant/destination → author a flagged syllable `.txt` (hybrid seeded-then-extended method) → register the constant → add a smoke spec and README entry → verify by parse-check and by sampling composed names. The skill is registered in the project README. A final end-to-end task exercises the skill against "german curse words" to prove it works.
8
+
9
+ **Tech Stack:** Markdown + YAML frontmatter (skill), Ruby 3.4+ / RSpec (the gem under test), the language-file DSL defined in `lib/random_name_generator/syllable.rb`.
10
+
11
+ ## Global Constraints
12
+
13
+ - **Language-file DSL (verbatim from `syllable.rb`):** one syllable per line; leading `-` = prefix bucket, leading `+` = suffix bucket, no sign = middle bucket. Flags: `+v` next-must-start-vowel, `+c` next-must-start-consonant, `-v` this-follows-vowel-ending, `-c` this-follows-consonant-ending. Order of flags is not significant; separated by whitespace.
14
+ - **Bucket sizing:** ~20–40 syllables per bucket (pre / mid / sur), matching `lib/languages/goblin.txt`.
15
+ - **Edgy-theme routing:** curse/insult/swear/NSFW/drunk themes → `lib/languages/experimental/`; tame themes → `lib/languages/`.
16
+ - **Git is manual:** the assistant must NOT run any state-changing git command. Every "Commit" step below is a **suggested command surfaced to the user to run themselves**, never executed by the assistant. This applies inside the skill too.
17
+ - **No overwrite:** never clobber an existing language file or `File.new` constant without explicit user confirmation.
18
+ - **flip_mode arrays are hand-curated:** do NOT add generated languages to `flip_mode` / `flip_mode_cyrillic`.
19
+ - **README Skills rule (project convention):** when a skill is added, link it in `README.md` under `## Skills` using the skill's `name` as link text and its `description` as the blurb.
20
+
21
+ ---
22
+
23
+ ### Task 1: Author the `/lang-gen` SKILL.md
24
+
25
+ **Files:**
26
+ - Create: `.claude/skills/lang-gen/SKILL.md`
27
+
28
+ **Interfaces:**
29
+ - Produces: a skill named `lang-gen`, invocable via `/lang-gen <theme>`, discoverable in the skills list. No code symbols.
30
+
31
+ - [ ] **Step 1: Create the skill file with frontmatter and full workflow**
32
+
33
+ Create `.claude/skills/lang-gen/SKILL.md` with exactly this content:
34
+
35
+ ````markdown
36
+ ---
37
+ name: lang-gen
38
+ description: Generate a new random_name_generator language from a free-text theme (e.g. "german curse words") — assembles flagged pre/mid/sur syllable collections, registers the File constant, adds a smoke spec and README entry, and samples names to verify. Use when the user types /lang-gen or asks to create, generate, or add a new language, dialect, or syllable file for the name generator.
39
+ ---
40
+
41
+ # lang-gen
42
+
43
+ Turn a free-text theme into a fully integrated `random_name_generator`
44
+ language file. Invoked as `/lang-gen <theme>`, e.g. `/lang-gen german curse words`.
45
+
46
+ ## The language-file DSL
47
+
48
+ Authoritative source: `lib/random_name_generator/syllable.rb`. Each line of a
49
+ language `.txt` is one syllable:
50
+
51
+ - Leading `-` → **prefix** (pre) bucket — a name beginning.
52
+ - Leading `+` → **suffix** (sur) bucket — a name ending.
53
+ - No sign → **middle** (mid) bucket — an interior fragment.
54
+
55
+ Optional whitespace-separated flags after the syllable constrain adjacency:
56
+
57
+ - `+v` — the NEXT syllable must start with a vowel.
58
+ - `+c` — the NEXT syllable must start with a consonant.
59
+ - `-v` — THIS syllable may only follow one ending in a vowel.
60
+ - `-c` — THIS syllable may only follow one ending in a consonant.
61
+
62
+ A name needs all three buckets non-empty. `Generator#compose` picks a prefix,
63
+ fills with middles, ends with a suffix, honoring the flags.
64
+
65
+ ## Workflow
66
+
67
+ Follow these steps in order. Do not skip verification.
68
+
69
+ ### 1. Parse the theme and derive names
70
+
71
+ From the argument string derive and then **show the user for confirmation**:
72
+
73
+ - **slug** — concise kebab-case, 1–2 meaningful words, drop filler ("words",
74
+ "generator", articles). `german curse words` → `german-curse`.
75
+ - **constant** — SCREAMING_SNAKE of the slug. `german-curse` → `GERMAN_CURSE`.
76
+ - **destination** — edgy themes (curse, insult, swear, NSFW, drunk, etc.) →
77
+ `lib/languages/experimental/<slug>.txt`; tame themes →
78
+ `lib/languages/<slug>.txt`.
79
+
80
+ Before writing anything, check for collisions: if the target `.txt` OR the
81
+ constant already exists, STOP and ask the user how to proceed. Never overwrite.
82
+
83
+ ### 2. Author the syllable file (hybrid: seed, then extend)
84
+
85
+ 1. Recall a handful of **real roots** for the theme. (German curses: `schei`,
86
+ `arsch`, `sau`, `verdammt`, `dreck`, `mist`, `depp`, `blöd`, …)
87
+ 2. Slot fragments into buckets: prefixes (`-`) = natural beginnings, middles
88
+ (bare) = connective interiors, suffixes (`+`) = natural endings / intensifiers.
89
+ 3. **Extend** each bucket with same-flavor **invented** syllables until each
90
+ holds ~20–40 entries (match `lib/languages/goblin.txt` scale).
91
+ 4. Add `+v/+c/-v/-c` flags **only where they prevent awkward clusters** — e.g. a
92
+ consonant-final prefix that would collide, or a lone vowel that reads badly
93
+ after another vowel. Most lines carry no flag. Keep it judicious.
94
+
95
+ Write the file to the destination from step 1.
96
+
97
+ ### 3. Register the constant
98
+
99
+ Edit `lib/random_name_generator.rb`. Add, next to the matching group of
100
+ constants (edgy → under the `# Experimental` comment; tame → with the curated
101
+ constants):
102
+
103
+ ```ruby
104
+ CONSTANT_NAME = File.new("#{dirname}/languages/<relative/path>.txt")
105
+ ```
106
+
107
+ Do NOT touch `flip_mode` or `flip_mode_cyrillic` — those arrays are curated.
108
+
109
+ ### 4. Add a smoke spec
110
+
111
+ Add an example to `spec/random_name_generator_spec.rb` following existing
112
+ conventions (see the `with languages` context). It must assert the constant is a
113
+ `File`, its `path` includes the expected filename, and that a `Generator` built
114
+ from it composes a non-empty `String`:
115
+
116
+ ```ruby
117
+ it "when it has a <Theme> language" do
118
+ expect(RandomNameGenerator::CONSTANT_NAME).to be_a(File)
119
+ expect(RandomNameGenerator::CONSTANT_NAME.path).to include("languages/<relative/path>.txt")
120
+ name = RandomNameGenerator::Generator.new(RandomNameGenerator::CONSTANT_NAME).compose
121
+ expect(name).to be_a(String)
122
+ expect(name).not_to be_empty
123
+ end
124
+ ```
125
+
126
+ ### 5. Add a README entry
127
+
128
+ Add the new language to `README.md`. Edgy/experimental languages go under a
129
+ short "Experimental languages" note; tame ones join the curated list. Link to
130
+ the file, matching how the curated four are listed.
131
+
132
+ ### 6. Verify — parse-check then sample
133
+
134
+ - **Parse-check:** confirm every line is a valid syllable and all three buckets
135
+ are non-empty. Fastest via the gem:
136
+
137
+ ```bash
138
+ bundle exec ruby -Ilib -rrandom_name_generator -e '
139
+ g = RandomNameGenerator::Generator.new(RandomNameGenerator::CONSTANT_NAME)
140
+ abort "empty pre" if g.pre_syllables.empty?
141
+ abort "empty mid" if g.mid_syllables.empty?
142
+ abort "empty sur" if g.sur_syllables.empty?
143
+ puts "buckets OK: #{g.pre_syllables.size}/#{g.mid_syllables.size}/#{g.sur_syllables.size}"
144
+ '
145
+ ```
146
+
147
+ - **Sample:** print ~10 composed names for the user to eyeball:
148
+
149
+ ```bash
150
+ bundle exec ruby -Ilib -rrandom_name_generator -e '
151
+ g = RandomNameGenerator::Generator.new(RandomNameGenerator::CONSTANT_NAME)
152
+ 10.times { puts g.compose }
153
+ '
154
+ ```
155
+
156
+ - **Run the spec:** `bundle exec rspec spec/random_name_generator_spec.rb`
157
+
158
+ If names look broken or monotonous, iterate on the `.txt` (more variety, better
159
+ flags) and re-sample before finishing.
160
+
161
+ ### 7. Hand off the commit
162
+
163
+ Git is manual. Do NOT run git yourself. Surface the exact command for the user:
164
+
165
+ ```bash
166
+ git add lib/languages README.md lib/random_name_generator.rb spec/random_name_generator_spec.rb && git commit -m "Add <Theme> language via /lang-gen"
167
+ ```
168
+
169
+ ## Guardrails
170
+
171
+ - Never overwrite an existing language file or constant without confirmation.
172
+ - Never run state-changing git commands — always suggest them.
173
+ - Keep bucket sizes and flag style consistent with existing `lib/languages/*.txt`.
174
+ ````
175
+
176
+ - [ ] **Step 2: Verify the skill file is structurally valid**
177
+
178
+ Run:
179
+
180
+ ```bash
181
+ head -5 .claude/skills/lang-gen/SKILL.md && echo "---" && grep -c '^### [1-7]\.' .claude/skills/lang-gen/SKILL.md
182
+ ```
183
+
184
+ Expected: the frontmatter shows `name: lang-gen` and the `description:` line; the grep prints `7` (all seven workflow steps present).
185
+
186
+ - [ ] **Step 3: Commit (suggest to user — do not run)**
187
+
188
+ Surface this command for the user:
189
+
190
+ ```bash
191
+ git add .claude/skills/lang-gen/SKILL.md && git commit -m "Add /lang-gen skill"
192
+ ```
193
+
194
+ ---
195
+
196
+ ### Task 2: Register the skill in the project README
197
+
198
+ **Files:**
199
+ - Modify: `README.md`
200
+
201
+ **Interfaces:**
202
+ - Consumes: the `name` (`lang-gen`) and `description` authored in Task 1.
203
+ - Produces: a `## Skills` section linking the skill, satisfying the project's README rule.
204
+
205
+ - [ ] **Step 1: Add the Skills section**
206
+
207
+ Append a `## Skills` section to `README.md` (place it before the license footer). Use exactly:
208
+
209
+ ```markdown
210
+ ## Skills
211
+
212
+ - [lang-gen](.claude/skills/lang-gen/SKILL.md) — Generate a new random_name_generator language from a free-text theme (e.g. "german curse words") — assembles flagged pre/mid/sur syllable collections, registers the File constant, adds a smoke spec and README entry, and samples names to verify.
213
+ ```
214
+
215
+ - [ ] **Step 2: Verify the link and file line up**
216
+
217
+ Run:
218
+
219
+ ```bash
220
+ grep -n '^## Skills' README.md && test -f .claude/skills/lang-gen/SKILL.md && echo "target exists"
221
+ ```
222
+
223
+ Expected: prints the `## Skills` line number and `target exists`.
224
+
225
+ - [ ] **Step 3: Commit (suggest to user — do not run)**
226
+
227
+ Surface this command for the user:
228
+
229
+ ```bash
230
+ git add README.md && git commit -m "Register /lang-gen in README Skills section"
231
+ ```
232
+
233
+ ---
234
+
235
+ ### Task 3: End-to-end validation — generate the `german-curse` language
236
+
237
+ This task runs the finished skill against the motivating example to prove the
238
+ whole workflow produces working output. It is the plan's integration test.
239
+
240
+ **Files (produced by running the skill):**
241
+ - Create: `lib/languages/experimental/german-curse.txt`
242
+ - Modify: `lib/random_name_generator.rb` (add `GERMAN_CURSE` constant under `# Experimental`)
243
+ - Modify: `spec/random_name_generator_spec.rb` (add German-curse smoke example)
244
+ - Modify: `README.md` (experimental-languages note)
245
+
246
+ **Interfaces:**
247
+ - Consumes: the `.claude/skills/lang-gen/SKILL.md` workflow from Task 1.
248
+ - Produces: `RandomNameGenerator::GERMAN_CURSE` — a `File` at `languages/experimental/german-curse.txt`, usable via `RandomNameGenerator::Generator.new(RandomNameGenerator::GERMAN_CURSE)`.
249
+
250
+ - [ ] **Step 1: Invoke the skill**
251
+
252
+ Run `/lang-gen german curse words` and follow the SKILL.md workflow. Confirm the
253
+ derived slug `german-curse`, constant `GERMAN_CURSE`, destination
254
+ `lib/languages/experimental/german-curse.txt`.
255
+
256
+ - [ ] **Step 2: Verify buckets parse and are non-empty**
257
+
258
+ Run:
259
+
260
+ ```bash
261
+ bundle exec ruby -Ilib -rrandom_name_generator -e '
262
+ g = RandomNameGenerator::Generator.new(RandomNameGenerator::GERMAN_CURSE)
263
+ abort "empty pre" if g.pre_syllables.empty?
264
+ abort "empty mid" if g.mid_syllables.empty?
265
+ abort "empty sur" if g.sur_syllables.empty?
266
+ puts "buckets OK: #{g.pre_syllables.size}/#{g.mid_syllables.size}/#{g.sur_syllables.size}"
267
+ '
268
+ ```
269
+
270
+ Expected: `buckets OK: N/N/N` with each N in roughly 20–40.
271
+
272
+ - [ ] **Step 3: Sample names**
273
+
274
+ Run:
275
+
276
+ ```bash
277
+ bundle exec ruby -Ilib -rrandom_name_generator -e '
278
+ g = RandomNameGenerator::Generator.new(RandomNameGenerator::GERMAN_CURSE)
279
+ 10.times { puts g.compose }
280
+ '
281
+ ```
282
+
283
+ Expected: 10 varied, pronounceable, German-flavored strings. If monotonous or broken, iterate on the `.txt` and repeat.
284
+
285
+ - [ ] **Step 4: Run the full test suite**
286
+
287
+ Run: `bundle exec rspec`
288
+
289
+ Expected: all examples pass, including the new German-curse smoke example.
290
+
291
+ - [ ] **Step 5: Commit (suggest to user — do not run)**
292
+
293
+ Surface this command for the user:
294
+
295
+ ```bash
296
+ git add lib/languages/experimental/german-curse.txt lib/random_name_generator.rb spec/random_name_generator_spec.rb README.md && git commit -m "Add German curse language via /lang-gen"
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Self-Review
302
+
303
+ **Spec coverage:**
304
+ - Trigger & arg parsing → Task 1 §1. ✓
305
+ - Slug/constant/destination derivation + confirm → Task 1 §1. ✓
306
+ - Edgy-theme routing → Task 1 §1 + Global Constraints. ✓
307
+ - Collision guard / no overwrite → Task 1 §1 + Guardrails. ✓
308
+ - Hybrid seeded-then-extended generation → Task 1 §2. ✓
309
+ - ~20–40 per bucket + smart flags → Task 1 §2 + Global Constraints. ✓
310
+ - Constant registration, flip_mode untouched → Task 1 §3. ✓
311
+ - Smoke spec → Task 1 §4. ✓
312
+ - README language entry → Task 1 §5. ✓
313
+ - Verification: parse-check + sample → Task 1 §6, exercised in Task 3. ✓
314
+ - Git manual → Global Constraints + every commit step + Task 1 §7. ✓
315
+ - Skill location `.claude/skills/lang-gen/` → Task 1. ✓
316
+ - README `## Skills` registration → Task 2. ✓
317
+
318
+ **Placeholder scan:** No TBD/TODO; all code, commands, and skill body are literal. ✓
319
+
320
+ **Type consistency:** `GERMAN_CURSE`, `german-curse.txt`, `languages/experimental/german-curse.txt`, and the `pre_syllables`/`mid_syllables`/`sur_syllables` reader names (from `random_name_generator.rb`) are used consistently across Tasks 1 and 3. ✓