mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 10:17:06 +00:00
Fix release for 1.1.1: the minimal path end to end, engine commands that run on Godot, Unity and Unreal, hook warnings you can see, and verdicts that say when they could not check. Details in CHANGELOG.md; upgrade steps in UPGRADING.md (v1.1.1 → v1.1.2). Fixes #67 Fixes #131 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
249 lines
10 KiB
Markdown
249 lines
10 KiB
Markdown
# Skill Test Spec: /localize
|
|
|
|
## Skill Summary
|
|
|
|
`/localize` runs the localization pipeline through one required subcommand:
|
|
`scan`, `extract`, `validate`, `status`, `brief`, `cultural-review`,
|
|
`vo-pipeline`, `rtl-check`, `freeze` or `qa`. It works on a single source string
|
|
table under `assets/data/strings/` (`strings-en.json` is the English source; the
|
|
other locales sit beside it) and writes reports under `production/localization/`.
|
|
|
|
`scan`, `validate` and `status` are read-only. `extract` shows a diff of new
|
|
keyed entries and asks "May I write these new entries to
|
|
`assets/data/strings/strings-en.json`?" before appending only the diff; its
|
|
verdict is **COMPLETE**. With no subcommand the skill prints usage and stops with
|
|
verdict **FAIL** — missing required subcommand. A scan whose code root cannot be
|
|
resolved reports `NOT ASSESSED — code root unresolved`; a status run with no
|
|
string table reports `NOT ASSESSED — no string table found`. `cultural-review`
|
|
and `qa` spawn `localization-lead`; `qa` issues a per-locale
|
|
PASS / PASS WITH CONDITIONS / NOT ASSESSED / FAIL verdict, first match FAIL →
|
|
NOT ASSESSED → PASS WITH CONDITIONS → PASS. Its checks are playthrough-based, so a
|
|
locale nobody has played is NOT ASSESSED, and the release gate does not count it
|
|
as passed. No director gates apply.
|
|
|
|
---
|
|
|
|
## Static Assertions (Structural)
|
|
|
|
Checked against the SKILL.md by `/skill-test spec` — no fixture needed.
|
|
|
|
- [ ] Has required frontmatter fields: `name`, `description`, `argument-hint`, `user-invocable`, `allowed-tools`
|
|
- [ ] Has ≥2 phase headings
|
|
- [ ] Contains verdict keywords: COMPLETE, FAIL, NOT ASSESSED, PASS WITH CONDITIONS
|
|
- [ ] Contains "May I write" collaborative protocol language before writing the string table or a report
|
|
- [ ] Has a next-step handoff (the Recommended Workflow chain ending in `/gate-check release`)
|
|
- [ ] The QA gate note is tiered: at `workflow: full` the Polish → Release gate requires PASS or PASS WITH CONDITIONS for every translated locale being shipped (recommended at `standard`, dropped at `minimal`)
|
|
- [ ] The `freeze` question names the file it writes — "This writes `production/localization/freeze-status.md`" — before the user answers
|
|
|
|
---
|
|
|
|
## Director Gate Checks
|
|
|
|
None. `/localize` is a pipeline utility and spawns no director. The only agent
|
|
it spawns is `localization-lead` (an operations-tier agent), and only in the
|
|
`cultural-review` and `qa` modes.
|
|
|
|
---
|
|
|
|
## Test Cases
|
|
|
|
### Case 1: Extract — New Strings Keyed and Appended After Approval
|
|
|
|
**Fixture:**
|
|
- `project.yaml` has `engine.name: Godot`, so the code root is `src/`
|
|
- `src/ui/hud.gd` wraps three strings in `tr()` that have no entry in
|
|
`assets/data/strings/strings-en.json`
|
|
- No `production/localization/freeze-status.md` exists
|
|
|
|
**Input:** `/localize extract`
|
|
|
|
**Expected behavior:**
|
|
1. Skill scans source files for localized string references and compares them
|
|
against the table in `assets/data/strings/`
|
|
2. Skill proposes one new entry per unkeyed string, with a key in the form
|
|
`[category].[subcategory].[description]` (e.g. `ui.hud.health_label`)
|
|
3. Each new entry carries a `context` field: where it appears, maximum length,
|
|
placeholder meaning
|
|
4. Skill presents the diff and asks "May I write these new entries to
|
|
`assets/data/strings/strings-en.json`?"
|
|
5. On approval it writes only the new entries (not a full replacement);
|
|
verdict is COMPLETE
|
|
|
|
**Assertions:**
|
|
- [ ] Proposed keys follow `[category].[subcategory].[description]`
|
|
- [ ] Every new entry includes a `context` field
|
|
- [ ] The diff is shown and "May I write" names `assets/data/strings/strings-en.json` before any write
|
|
- [ ] Only the three new entries are written — existing entries are not rewritten
|
|
- [ ] Verdict is COMPLETE
|
|
|
|
---
|
|
|
|
### Case 2: No Subcommand — Usage and FAIL
|
|
|
|
**Fixture:**
|
|
- Any project state
|
|
|
|
**Input:** `/localize`
|
|
|
|
**Expected behavior:**
|
|
1. Skill finds no subcommand in the argument
|
|
2. Skill outputs usage (the ten modes) and stops
|
|
3. Verdict is FAIL — missing required subcommand
|
|
|
|
**Assertions:**
|
|
- [ ] Usage listing the available modes is printed
|
|
- [ ] Verdict is FAIL with the reason "missing required subcommand"
|
|
- [ ] No scan, extract or validation work is performed
|
|
- [ ] No file is written and no "May I write" ask appears
|
|
|
|
---
|
|
|
|
### Case 3: Validate — Gaps Reported by Locale, Nothing Written
|
|
|
|
**Fixture:**
|
|
- `assets/data/strings/` holds `strings-en.json`, `strings-fr.json` and
|
|
`strings-de.json`
|
|
- `strings-de.json` lacks 4 keys present in the English source
|
|
- One French entry omits the `{playerName}` placeholder its English source has
|
|
|
|
**Input:** `/localize validate`
|
|
|
|
**Expected behavior:**
|
|
1. Skill reads every string table file in `assets/data/strings/`
|
|
2. For `de` it reports the 4 keys as Completeness gaps
|
|
3. For `fr` it reports a Placeholder mismatch on the affected key
|
|
4. Results are grouped by locale and severity
|
|
5. Skill writes nothing — validate is read-only
|
|
|
|
**Assertions:**
|
|
- [ ] The 4 missing keys are named and attributed to the `de` locale
|
|
- [ ] The placeholder mismatch is reported against the `fr` locale and its key
|
|
- [ ] Output is grouped by locale and severity
|
|
- [ ] No file is written or modified, and no "May I write" ask appears
|
|
|
|
---
|
|
|
|
### Case 4: Status With No String Table — NOT ASSESSED
|
|
|
|
**Fixture:**
|
|
- `assets/data/strings/` does not exist
|
|
|
|
**Input:** `/localize status`
|
|
|
|
**Expected behavior:**
|
|
1. Skill looks for the source string table and finds none
|
|
2. The whole status output is `NOT ASSESSED — no string table found`
|
|
3. Skill does not produce a coverage matrix of zeros, and does not pre-fill the
|
|
source row as `100%`
|
|
|
|
**Assertions:**
|
|
- [ ] Output is `NOT ASSESSED — no string table found`
|
|
- [ ] No coverage matrix with zero counts is produced
|
|
- [ ] The source locale is not reported as `100%` coverage
|
|
- [ ] No file is written (status is read-only)
|
|
|
|
---
|
|
|
|
### Case 5: Director Gate Check — None; Cultural Review Uses localization-lead
|
|
|
|
**Fixture:**
|
|
- `assets/data/strings/strings-en.json` exists with player-facing strings
|
|
- Any review mode
|
|
|
|
**Input:** `/localize cultural-review`
|
|
|
|
**Expected behavior:**
|
|
1. Skill spawns `localization-lead` to audit strings and assets for cultural
|
|
sensitivity
|
|
2. Findings are presented as a table with a severity of BLOCKING, ADVISORY or
|
|
NOTE per finding
|
|
3. Skill asks "May I write this cultural review report to
|
|
`production/localization/cultural-review-[date].md`?"
|
|
4. No director agent is spawned and no gate ID appears in output
|
|
|
|
**Assertions:**
|
|
- [ ] `localization-lead` is the only agent spawned
|
|
- [ ] No director gate (creative, technical, producer, art) is invoked and no gate skip message appears
|
|
- [ ] Each finding carries BLOCKING, ADVISORY or NOTE severity
|
|
- [ ] "May I write" names `production/localization/cultural-review-[date].md` before the report is written
|
|
|
|
---
|
|
|
|
### Case 6: Scan With an Unresolved Code Root — NOT ASSESSED, never "no hardcoded strings"
|
|
|
|
**Fixture:**
|
|
- `project.yaml` has no `engine.name`; `.claude/docs/technical-preferences.md`
|
|
reads `[TO BE CONFIGURED]`
|
|
- Both `src/` and `Assets/` exist and hold UI code with hardcoded strings
|
|
(ambiguous tree)
|
|
|
|
**Input:** `/localize scan`
|
|
|
|
**Expected behavior:**
|
|
1. Skill tries to resolve the code root and cannot (no engine, two candidate roots)
|
|
2. It reports `NOT ASSESSED — code root unresolved` for the hardcoded-string
|
|
search and says which checks did not run
|
|
3. It does not guess `src/`, and does not report zero hits or "no hardcoded
|
|
strings found" — that would read as "nothing to localize"
|
|
4. Nothing is written — scan is read-only
|
|
|
|
**Assertions:**
|
|
- [ ] Output reads `NOT ASSESSED — code root unresolved` for the code search
|
|
- [ ] No "no hardcoded strings" or zero-hit result is reported
|
|
- [ ] The code root is not assumed to be `src/`
|
|
- [ ] No file is written and no "May I write" ask appears
|
|
|
|
---
|
|
|
|
### Case 7: QA on a Locale Nobody Has Played — NOT ASSESSED
|
|
|
|
**Fixture:**
|
|
- `assets/data/strings/strings-en.json` and `strings-fr.json` exist and validate
|
|
cleanly
|
|
- No one has played the French build: there are no in-game observations for the
|
|
functional, overflow, contextual-accuracy or VO checks
|
|
|
|
**Input:** `/localize qa`
|
|
|
|
**Expected behavior:**
|
|
1. Skill spawns `localization-lead` for the QA plan
|
|
2. The playthrough-based checks have no results, and no BLOCKING finding is open,
|
|
so the French verdict is **NOT ASSESSED**, naming each check that did not run
|
|
3. The verdict is not PASS or PASS WITH CONDITIONS on the strength of the string
|
|
tables alone
|
|
4. Skill asks "May I write this localization QA report to
|
|
`production/localization/loc-qa-fr-[date].md`?"; the report says the locale
|
|
has not passed QA for the release gate
|
|
|
|
**Assertions:**
|
|
- [ ] The French Status is NOT ASSESSED, with the unrun checks named
|
|
- [ ] No PASS or PASS WITH CONDITIONS is issued for an unplayed locale
|
|
- [ ] "May I write" names the loc-qa report path before it is written
|
|
- [ ] The report does not present the locale as cleared for the Polish → Release gate
|
|
|
|
---
|
|
|
|
## Protocol Compliance
|
|
|
|
- [ ] Stops with usage and verdict FAIL when no subcommand is given
|
|
- [ ] `scan`, `validate` and `status` write no files
|
|
- [ ] Asks "May I write" with the target path before writing the string table (extract) or any report (brief, cultural-review, vo-pipeline script, rtl-check, qa)
|
|
- [ ] Extract writes only the diff of new entries, never a full replacement of the table
|
|
- [ ] Reports NOT ASSESSED instead of zero results when the code root or the string table is missing
|
|
- [ ] `qa` issues PASS, PASS WITH CONDITIONS, NOT ASSESSED or FAIL per locale, first match FAIL → NOT ASSESSED → PASS WITH CONDITIONS → PASS
|
|
- [ ] Ends with the Recommended Workflow chain / `/gate-check release` handoff
|
|
|
|
---
|
|
|
|
## Coverage Notes
|
|
|
|
- `scan` with a resolved code root (findings with file paths and line numbers)
|
|
is not separately tested; Case 6 covers the unresolved root.
|
|
- `extract` while `freeze-status.md` shows Status: ACTIVE (new keys appended to
|
|
`## Post-Freeze Changes` with a freeze-violation warning) is not tested.
|
|
- `freeze` (pre-freeze checklist and `AskUserQuestion` [A]/[B]), `brief`,
|
|
`vo-pipeline` and `rtl-check` are not exercised by a dedicated case; `qa` is
|
|
covered only for its NOT ASSESSED branch (Case 7).
|
|
- The `qa` gate note — a FAIL blocks release for that locale only — needs a live
|
|
run with multiple locales to verify.
|