Naming discipline drift audit — Phase C input spec
Naming discipline drift audit — Phase C input spec
1. Summary
D-017 (canonised 2026-05-20, commit 7a1d31a) established the three-name discipline for all WalkRPG entities: every entity carries a bare EN handle (its primary key), a canonical PL name, and a canonical EN name, all registered in data/src/content/_glossary.ts. Phase A wave 1 (commit b03798e) shipped pnpm lint:naming in warn mode with three rules — filename-matches-handle, handle-in-glossary, and en-body-no-untracked-pl. Phase A wave 2 (commit 5dcac07) populated the glossary with 17 bootstrap entries, ~30 mechanical entries, and 11 Phase C pending entries, reducing the handle-in-glossary rule from 70 warnings to 0. This audit catalogues the 30 warnings still open after wave 2: 6 under filename-matches-handle (quest filename prefix divergence), 0 under handle-in-glossary (clean), and 24 under en-body-no-untracked-pl (PL tokens in EN body strings). It also enumerates the 11 glossary entries marked PENDING_PHASE_C_PICK that require a four-phase name pick from narrative-designer. Together, these form the complete input specification for Phase C.
2. Lint warn-list snapshot (current state)
Captured 2026-05-20. Run: pnpm lint:naming.
$ node scripts/lint-naming.mjslint:naming — WARN mode, exit 0
-- filename-matches-handle: 6 warning(s) -- data/src/content/quests/quest-001-first-road.ts:0 — filename-matches-handle — filename slug "quest-001-first-road" != id handle "001-first-road" (expected file "001-first-road.ts") data/src/content/quests/quest-002-pieczetarnia-milczy.ts:0 — filename-matches-handle — filename slug "quest-002-pieczetarnia-milczy" != id handle "002-pieczetarnia-milczy" (expected file "002-pieczetarnia-milczy.ts") data/src/content/quests/quest-003-dzwoniacy-magazyn.ts:0 — filename-matches-handle — filename slug "quest-003-dzwoniacy-magazyn" != id handle "003-dzwoniacy-magazyn" (expected file "003-dzwoniacy-magazyn.ts") data/src/content/quests/quest-004-polowa-rejestru.ts:0 — filename-matches-handle — filename slug "quest-004-polowa-rejestru" != id handle "004-polowa-rejestru" (expected file "004-polowa-rejestru.ts") data/src/content/quests/quest-005-niemilknacy-kurier.ts:0 — filename-matches-handle — filename slug "quest-005-niemilknacy-kurier" != id handle "005-niemilknacy-kurier" (expected file "005-niemilknacy-kurier.ts") data/src/content/quests/quest-006-najstarsze-biuro.ts:0 — filename-matches-handle — filename slug "quest-006-najstarsze-biuro" != id handle "006-najstarsze-biuro" (expected file "006-najstarsze-biuro.ts")
-- handle-in-glossary: 0 warning(s) --
-- en-body-no-untracked-pl: 24 warning(s) -- data/src/content/npcs/kepka-witness-bookkeeper.ts:12 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...Pan Kępka..." data/src/content/npcs/kepka-witness-bookkeeper.ts:22 — en-body-no-untracked-pl — en literal contains PL diacritic "ł" near: "...per to Janisław „Three-R..." data/src/content/npcs/pine-half-century.ts:11 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...Wnęt Pine-Half..." data/src/content/npcs/pine-half-century.ts:22 — en-body-no-untracked-pl — en literal contains PL diacritic "ó" near: "...e surname „Półwiek" was ..." data/src/content/npcs/stary-marno-niedoczas.ts:23 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...He says „idę i z tego ż..." data/src/content/quests/quest-003-dzwoniacy-magazyn.ts:58 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...sement pieczętarka on du..." data/src/content/quests/quest-003-dzwoniacy-magazyn.ts:66 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...), the pieczętarka's one..." data/src/content/quests/quest-004-polowa-rejestru.ts:29 — en-body-no-untracked-pl — en literal contains PL diacritic "ó" near: "... of one — „pójdziesz, po..." data/src/content/quests/quest-004-polowa-rejestru.ts:68 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...le gives. Wnęt Sosnowy-P..." data/src/content/quests/quest-004-polowa-rejestru.ts:85 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...ouse mark Wnęt copied on..." data/src/content/quests/quest-004-polowa-rejestru.ts:106 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...trip with Wnęt's copied ..." data/src/content/quests/quest-005-niemilknacy-kurier.ts:73 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...ing. The urzędnik at the..." data/src/content/quests/quest-005-niemilknacy-kurier.ts:90 — en-body-no-untracked-pl — en literal contains PL diacritic "ń" near: "...g — „znam pańską obrączk..." data/src/content/quests/quest-005-niemilknacy-kurier.ts:112 — en-body-no-untracked-pl — en literal contains PL diacritic "ó" near: "...for two kroków on either..." data/src/content/quests/quest-005-niemilknacy-kurier.ts:138 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...e day — „dziękuję panu, ..." data/src/content/quests/quest-006-najstarsze-biuro.ts:18 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "..., do kogo idę. Pytaj mni..." data/src/content/quests/quest-006-najstarsze-biuro.ts:47 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...ahead. Pan Kępka — Janis..." data/src/content/quests/quest-006-najstarsze-biuro.ts:68 — en-body-no-untracked-pl — en literal contains PL diacritic "ł" near: "...3 r. po Pomyłce". The pl..." data/src/content/quests/quest-006-najstarsze-biuro.ts:84 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...Pan Kępka receive..." data/src/content/quests/quest-006-najstarsze-biuro.ts:108 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "...Pan Kępka turns t..." data/src/content/quests/quest-006-najstarsze-biuro.ts:130 — en-body-no-untracked-pl — en literal contains PL diacritic "ą" near: "...i Pod Wczesną Pieczęcią ..." data/src/content/materials/bound-soot.ts:15 — en-body-no-untracked-pl — en literal contains PL diacritic "ó" near: "... the Drobnogórze pilgrim..." data/src/content/materials/frostlands-honey.ts:15 — en-body-no-untracked-pl — en literal contains PL diacritic "ó" near: "...ower-Drobnogórze tunnels..." data/src/content/opponents/frost-thing-slow-vent.ts:16 — en-body-no-untracked-pl — en literal contains PL diacritic "ę" near: "... below Pieczętarnia Mroz..."
Summary: 30 warning(s). Phase A acceptance: lint runs cleanly without crashing.Files scanned: 70. Glossary entries known: 64.Rule counts:
| Rule | Warnings |
|---|---|
filename-matches-handle | 6 |
handle-in-glossary | 0 |
en-body-no-untracked-pl | 24 |
| Total | 30 |
3. Drift categories — what Phase C must fix
3a. filename-matches-handle — quest prefix divergence (6 files)
All six quest files carry a quest-NNN- filename prefix. Their id-handles (the portion after the first dot in quest.<handle>) do not include that prefix. The lint rule expects the filename slug to equal the bare handle, so it fires for all six.
Eyes-on-file confirmation: every quest file verified. Each has id: QuestIdSchema.parse("quest.NNN-<slug>") where the bare handle is NNN-<slug> but the filename slug is quest-NNN-<slug>. The divergence is systematic and intentional — the prefix was added for file-tree readability, but the id-handle convention was set without it.
| Quest id handle | Current filename | Would rename to (option a) | Keep as (option c) |
|---|---|---|---|
001-first-road | quest-001-first-road.ts | 001-first-road.ts | quest-001-first-road.ts (lint exempt) |
002-pieczetarnia-milczy | quest-002-pieczetarnia-milczy.ts | 002-pieczetarnia-milczy.ts | quest-002-pieczetarnia-milczy.ts (lint exempt) |
003-dzwoniacy-magazyn | quest-003-dzwoniacy-magazyn.ts | 003-dzwoniacy-magazyn.ts | quest-003-dzwoniacy-magazyn.ts (lint exempt) |
004-polowa-rejestru | quest-004-polowa-rejestru.ts | 004-polowa-rejestru.ts | quest-004-polowa-rejestru.ts (lint exempt) |
005-niemilknacy-kurier | quest-005-niemilknacy-kurier.ts | 005-niemilknacy-kurier.ts | quest-005-niemilknacy-kurier.ts (lint exempt) |
006-najstarsze-biuro | quest-006-najstarsze-biuro.ts | 006-najstarsze-biuro.ts | quest-006-najstarsze-biuro.ts (lint exempt) |
Three resolution paths:
(a) Rename files to drop prefix. Filenames become 001-first-road.ts through 006-najstarsze-biuro.ts. Filename slug then matches id-handle exactly, rule passes with zero code changes. Cons: the quests/ directory loses the at-a-glance “this is a quest” visual cue; in a mixed content directory browsing is harder; any external references to the filename path (comments, wiki cross-refs, grep patterns) break. This is a real disruption for ~6 files now and compounds with every new quest.
(b) Strip the ordinal prefix from the id-handle. Handles become quest.first-road, quest.pieczetarnia-milczy, etc. Filename slug (quest-001-first-road) still does not match the new bare handle (first-road), so the rule would still fire unless files are also renamed. This option resolves nothing by itself and loses the ordinal anchor that canonically orders quests.
(c) Update the lint rule to recognise quest-NNN- as a canonical filename prefix for the quest schema kind. A one-line change in scripts/lint-naming.mjs: when the entity kind is quest, strip the leading quest- before comparing slug to handle. Filenames stay as they are; ids stay as they are; no content disruption; no cross-ref breaks. Cost: the rule becomes kind-aware rather than purely string-equal. If future schema kinds also need prefix handling, the pattern extends cleanly.
Recommendation: option (c). The quest-NNN- prefix is a meaningful ergonomic convention that makes the file tree self-documenting. Tooling should adapt to a well-established content convention, not the other way around. Option (a) causes immediate disruption with no semantic benefit; option (b) is strictly worse than (c) on every axis. Option (c) is a two-line script change. If CEO picks (a), the rename is mechanical and can be done by narrative-ops Sonnet; the qa-engineer would then verify all cross-refs in comments and wiki pages are updated (several files reference quest file paths by name in their JSDoc headers).
Note: Quest 001 (001-first-road) is the only quest with a fully completed transcreation note in the glossary (not PENDING_PHASE_C_PICK). Its filename-handle divergence is purely the quest- prefix issue — the handle itself is settled. Quests 002-006 have BOTH the filename divergence AND a PENDING_PHASE_C_PICK transcreation note (their handles are PL slugs awaiting rename). Section 3d covers those.
3b. handle-in-glossary — clean (0 warnings post-wave-2)
Pre-wave-2 this rule surfaced 70 warnings. Wave 2 (commit 5dcac07) populated the glossary with 64 unique bare handles covering all 70 entity files (6 kin-pair collisions where an item and its recipe share one bare handle, and a node and its mastery share another). Current state: 0 warnings. Glossary file: data/src/content/_glossary.ts. No Phase C action required for this rule — it is at zero.
3c. en-body-no-untracked-pl — loanword and proper-noun drift (24 warnings)
Each flagged token was verified against the entity file. Grouped by file, then by token, with category and Phase C handler.
File: data/src/content/npcs/kepka-witness-bookkeeper.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:12 | Kepka (PL: Kępka) | "Pan Kępka" in role field | Hybrid name (PL surname) | Glossary entry for handle kepka-witness-bookkeeper with four-phase EN pick; EN role field updated to use EN handle form once Phase C pick resolves the name. Also overlaps with 3d pending. |
:22 | Janislaw (PL: Janislaw with ogonek l) | "Janislaw \"Three-Receipts\" Mrzec" — lint fires on the l-with-stroke in the EN description field | Proper-noun personal name (Cholewa first name) | The EN field uses Janislaw (diacritic-free) in the role string at line 79, but the description field at line 83 contains the PL-diacritic form. Phase C: replace the diacritic form with Janislaw (diacritic-stripped transliteration, matching the glossary entry for three-receipts). No new glossary entry needed — mechanical EN body edit. |
File: data/src/content/npcs/pine-half-century.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:11 | Wnet (PL: Wn + ogonek-e + t) | "Wnet Pine-Half-Century" in name.en (with PL diacritic) | Hybrid name (PL first name particle in EN field) | Pending Phase C pick for pine-half-century glossary entry. The EN field currently carries the PL-diacritic first name — the four-phase pick must decide whether to keep it as an exotic transliteration or replace with an EN equivalent (e.g. Knoll). Phase C task: complete four-phase pick, update name.en and glossary en field accordingly. |
:22 | Polwiek (PL: P + o-acute + lwiek) | "the surname [PL-form] was awarded" in description.en | Quoted PL diegetic term (surname used in EN narration) | The EN description explains the character’s surname by quoting it in PL. After the four-phase pick resolves the EN form of the surname, Phase C replaces the PL quote with the EN equivalent (e.g. "Half-Century") and a parenthetical. Category is quoted PL dialog by appearance but is more precisely a diegetic proper-noun that needs translation. |
File: data/src/content/npcs/stary-marno-niedoczas.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:23 | idę (PL: i walk) | "He says „idę i z tego żyję"" in description.en | Quoted PL dialog — canonical character voice | This is Marno’s defining line, his only reliably finished sentence. Translating it mechanically loses the flat delivery that makes it land. Recommend: append an EN gloss in the same string — "He says [PL: ide i z tego zyje] — I walk and this is what I live by". CEO flag in Open Questions (§5) is required before Phase C acts on this pattern. |
File: data/src/content/quests/quest-003-dzwoniacy-magazyn.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:58 | pieczętarka | "the basement pieczętarka on duty" in beat-4 step EN | Diegetic loanword (Akademia institutional role) | Per CEO ratification 2026-05-20: anglicise diegetic loanwords. pieczetarka (PL diacritic form flagged by lint) = seal-maker / sealing-clerk. EN translation: seal-clerk or seal-keeper (narrative-designer to confirm). Phase C: add glossary entry pieczetarka → kind: loanword, en: "seal-clerk" (or chosen form); update all EN body occurrences. |
:66 | pieczętarka | "the pieczętarka's one-paragraph note" in beat-4 step EN | Same as above | Same handler — covered by the same glossary entry and EN body sweep. |
File: data/src/content/quests/quest-004-polowa-rejestru.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:29 | pojdziesz (PL diacritic form) | "„pójdziesz, popatrzysz, wrócisz, opowiesz"" in beat-1 step EN (Bertranda’s instruction) | Quoted PL dialog — canonical character voice | Bertranda’s half-finished sentence, a recurring structural motif. Like Marno’s line, translating removes diegetic texture. Recommend glossed-EN pattern with EN translation following the PL quote. CEO flag in Open Questions (§5). |
:68 | Wnet (PL diacritic form Wnet with ogonek-e) | "Wnet Sosnowy-Polwiek" in beat-3 step EN (PL diacritics in source) | Hybrid name (same token as pine-half-century.ts) | After Phase C pick for pine-half-century, this EN body occurrence is updated identically. Mechanical sweep once pick is made. |
:85 | Wnet (PL diacritic form) | "house mark Wnet copied onto" in beat-4 step EN | Hybrid name | Same — mechanical sweep after pick. |
:106 | Wnet (PL diacritic form) | "trip with Wnet's copied" in beat-5 step EN | Hybrid name | Same — mechanical sweep after pick. |
File: data/src/content/quests/quest-005-niemilknacy-kurier.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:73 | urzednik (PL diacritic form urzedni+ogonek) | "The urzędnik at the gate" in beat-2 step EN | Diegetic loanword (municipal gate official) | urzednik (diacritic form flagged) = official / gate clerk. EN: gate official or gate clerk. Phase C: add glossary entry urzednik → kind: loanword, en: "gate official"; update EN body globally (token also appears in quest-001 steps). |
:90 | panska (PL diacritic form) | "„znam pańską obrączkę. Drewniana. Nowsza niż moja koperta."" in beat-3 step EN | Quoted PL dialog — canonical character voice | Marno’s first line to the Walker. Formal-polite register (the honorific form) is load-bearing — establishes that Marno uses full formal address despite walking alone for 112 years. Recommend glossed-EN pattern. CEO flag (§5 Q2). |
:112 | krokow (PL diacritic form) | "for two kroków on either side" in beat-4 step EN | Diegetic loanword (unit of measure) | krok (genitive plural krokow with diacritic) = step/pace, the canonical WalkRPG unit. EN: strides or paces. Phase C: add glossary entry krok → kind: loanword, en: "pace"; update EN body. |
:138 | dziekuje (PL diacritic form) | "„dziękuję panu, że nie zwolnił."" in beat-5 step EN | Quoted PL dialog — canonical character voice | Marno’s final sentence to the Walker. Formal-polite register. Recommend glossed-EN pattern. CEO flag (§5 Q2). |
File: data/src/content/quests/quest-006-najstarsze-biuro.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:18 | ide (PL diacritic form) | "nie pytaj mnie, do kogo idę" in description.en (PL diacritic flagged) | Quoted PL dialog — canonical character voice | Marno’s central forward-bearing sentence; the thematic hinge of quests 005-006. Recommend same glossed-EN pattern. CEO flag (§5 Q2). |
:47 | Kepka (PL diacritic form) | "Pan Kępka — Janislaw" in beat-1 step EN | Hybrid name | After Phase C pick for kepka-witness-bookkeeper, all occurrences of the PL-diacritic form in EN body are updated to the resolved EN form. Six occurrences across quest-006. Mechanical sweep after pick. |
:68 | Pomylce (PL diacritic form, genitive of Pomylka) | "33 r. po Pomyłce" — the brass plate text in beat-2 step EN | Proper-noun place/era name | pomylka (diacritic: Pomylka with o-acute) = the canonical era-marking event, literally “the Mistake”. A proper-noun era name used on dated plaques. Phase C: add glossary entry pomylka → kind: place, authorise the PL form as a proper-noun loan (like “Anno Domini”) OR anglicise to “the Mistake” — CEO call (§5 Q3). |
:84 | Kepka (PL diacritic form) | "Pan Kępka receive" in beat-3 step EN | Hybrid name | Same sweep as :47. |
:108 | Kepka (PL diacritic form) | "Pan Kępka turns" in beat-4 step EN | Hybrid name | Same sweep as :47. |
:130 | Piecz + ecia with PL diacritics | "i Pod Wczesna Pieczecia" in beat-3 step EN (PL diacritics flagged) | Diegetic proper-noun — dissolved courier-house name | dom-pod-wczesna-pieczecia (diacritic form: Dom Kurierski Pod Wczesna Pieczecia) is the canonical name of the dissolved courier-house revealed in quest-006. A proper-noun institutional name; the Cholewa double-reading (sealed too soon / early sign) is cited as canonical. Phase C: add glossary entry dom-pod-wczesna-pieczecia → kind: place, en: "The Courier House of the Early Seal" (or narrative-designer’s pick). Register so lint authorises it as a proper-noun in EN body. |
File: data/src/content/materials/bound-soot.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:15 | Drobnogórze | "the Drobnogórze pilgrim route" in description.en | Proper-noun place name (toponym) | Drobnogórze (diacritic-form; handle: drobnogórze) is a named geographic area in the Frostlands (drobne gory = small mountains / smallcrags). Per toponym-preservation rule (2026-05-18), proper-noun place names are preserved in PL with pl == en. Phase C: add glossary entry drobnogórze → kind: place, pl == en, note covers toponym-preservation rule. |
File: data/src/content/materials/frostlands-honey.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:15 | Drobnogórze | "lower-Drobnogórze tunnels" in description.en | Proper-noun place name (toponym) | Same token and same handler as bound-soot. One glossary entry covers both occurrences. |
File: data/src/content/opponents/frost-thing-slow-vent.ts
| Lint ref | Token in EN body | Exact EN context | Category | Phase C handler |
|---|---|---|---|---|
:16 | Pieczetarnia (PL diacritic form) | "below Pieczętarnia Mroza" in description.en | Proper-noun place name (toponym) | pieczetarnia-mroza (handle; diacritic form flagged by lint) = the Seal-House of the Frost, a named Frostlands location introduced in quest-002. Proper-noun institutional toponym. Phase C: add glossary entry pieczetarnia-mroza → kind: place, pl == en (toponym preservation). |
Unique PL tokens summary by category
| Category | Unique tokens | Files affected | Phase C action type |
|---|---|---|---|
| Proper-noun place name (toponym) | drobnogórze, pieczetarnia-mroza, pomylka (handles; PL diacritic forms in EN body) | 3 files | Glossary entry (kind: place, pl == en), lint passes |
| Proper-noun institutional name | dom-pod-wczesna-pieczecia (handle; PL diacritic form in EN body) | 1 file (quest-006) | Glossary entry (kind: place), EN body may keep PL form with glossary authorisation |
| Diegetic loanword | pieczetarka, urzednik, krok / krokow (handles; PL diacritic forms in EN body) | 3 files | Glossary entry (kind: loanword) + EN body mechanical sweep |
| Quoted PL dialog | Five Marno/Bertranda character-voice lines (PL diacritic forms in EN body) | 4 files | CEO call first (§5 Q2); then glossed-EN pattern |
| Hybrid name particle | Wnet / Kepka / Janislaw (handles; PL diacritic forms in EN body) | 3 files | Four-phase pick resolves first; mechanical sweep after |
Total unique-token handlers: 12 distinct token types driving 24 warnings (some tokens appear multiple times across files/lines).
3d. Phase C pending registry (cross-check with glossary)
STATUS — PICKED 2026-05-20: all 11 four-phase picks landed on narrative-designer side. Decision log: ops/decisions/2026-05-20-phase-c-four-phase-picks.md. Glossary updated: PENDING_PHASE_C_PICK markers cleared, new handles registered, supersedes field populated for audit trail. The mechanical Phase C wave (entity file renames + EN body sweeps + loanword/toponym entries) is the follow-up.
NPCs (6 picked):
| Old bare handle | New bare handle | New const | Anchor type | Status |
|---|---|---|---|---|
stary-marno-niedoczas | undelivered-courier | undeliveredCourier | quirk (cosmic) | PICKED |
brodek-spozniony | half-sentence-sealer | halfSentenceSealer | quirk (diction) | PICKED |
pan-bezelec | unopened-door-warden | unopenedDoorWarden | quirk (Pratchett-paradox) | PICKED |
kepka-witness-bookkeeper | house-mark-reader | houseMarkReader | quirk (action) | PICKED |
pine-half-century | half-century-smolarz | halfCenturySmolarz | surname-honour + hybrid loanword | PICKED |
full-sentence-elder | full-sentence-elder | fullSentenceElder | quirk (diction) | VERIFIED (no rename) |
Quests (5 picked):
| Old bare handle | New bare handle | New const | Anchor type | Status |
|---|---|---|---|---|
002-pieczetarnia-milczy | 002-silent-seal-house | quest002SilentSealHouse | descriptor compressed | PICKED |
003-dzwoniacy-magazyn | 003-ringing-warehouse | quest003RingingWarehouse | descriptor literal | PICKED |
004-polowa-rejestru | 004-half-register | quest004HalfRegister | descriptor compressed | PICKED |
005-niemilknacy-kurier | 005-undelivered-loop | quest005UndeliveredLoop | quirk (structural) | PICKED |
006-najstarsze-biuro | 006-oldest-office | quest006OldestOffice | descriptor literal | PICKED |
Phase C picks landed — summary
The 11 picks honour the bound parameters from auto-mode resolution of Phase A Q1/Q2/Q3:
- Q1 (option c) — quest filenames will keep the
quest-NNN-prefix; new bare handles areNNN-<eng-slug>; full IDs arequest.NNN-<eng-slug>. Lint will be updated by tech-architect to accept the prefix. - Q2 (option a STRICT) — Marno’s PL character-voice quotes get translated in EN body in the mechanical wave; the handle picks do NOT anchor on PL phrases that the EN reader will never see (e.g. Marno’s handle does NOT use
„idę i z tego żyję"as anchor). - Q3 — toponyms get
kind:place+pl==en(mechanical wave); diegetic loanwords (smolarz, pieczetarka, urzednik, krok) getkind:loanword+ EN translation (mechanical wave). Thehouse-mark-readerandhalf-century-smolarzpicks integrate cleanly with these.
Three structural notes:
-
Quirk-over-role consistency. Five of six NPC picks use the quirk-anchor pattern (D-013/D-006/canonical-fact anchors). Only
full-sentence-elderwas verified rather than renamed — its existing handle IS the quirk-anchor; the verification documents the rationale and lifts the PENDING marker. -
Pratchett-paradox compound shape. Three NPC handles (
undelivered-courier,unopened-door-warden,half-sentence-sealer) use the same negated-compound shape asfaction.unfinished-guildandfaction.quiet-lights— the institution/character defined by what it does not do or cannot do. -
Chain-resonance.
npc.undelivered-courier↔quest.005-undelivered-loopmakes the Marno-Walker chain visible at the ID level;npc.half-sentence-sealer↔npc.full-sentence-eldermakes the Frostlands diction-axis pairing visible. The 18.05 rule (deeper anchor over visible symptom) drove both pairings.
Alternatives considered (preserved in the decision log per 18.05 audit-trail discipline):
- Marno:
unstopping-courier(body-fact, lost on depth) /looped-courier(spatial-fact, lost on slot fit). - Brodek:
belated-magister(Cholewa surname) /rotation-sealer(role). - Pan Bezelec:
night-warden(role) /without-light-warden(Cholewa surname). Pan Kępka:witness-bookkeeper(role) /unslept-witness(body-fact).Wnęt:half-century-resin-burner(fully-EN) /flood-survivor-smolarz(plot-fact).- Trudka:
wykuwisko-four-elder(role) /iron-walls-elder(Quest-002-outcome). - Quest 002:
002-seal-house-falls-silent(verbose) /002-listening-post(threshold not destination). - Quest 003:
003-warehouse-seventeen(toponym) /003-stamps-strike(verb-phrase). - Quest 004:
004-half-of-the-register(verbose) /004-resin-trail(mechanism not fact). - Quest 005:
005-unhushed-courier(literal, no chain) /005-companion-walk(mechanical). - Quest 006:
006-mokrych-stempli(toponym, lore-split) /006-wczesna-pieczec(content not location).
Cross-reference: 3c warnings overlapping with 3d pending:
The following files appear in BOTH the en-body-no-untracked-pl list (§3c) AND the Phase C pending registry (§3d), meaning one Phase C handler can resolve both:
kepka-witness-bookkeeper.ts— the PL-diacriticKepkatoken in EN body (§3c, 2 warnings) and thekepka-witness-bookkeeperpending four-phase pick (§3d) are resolved together. Once the four-phase pick settles the EN handle and EN name form, the EN body occurrences are updated in the same pass.pine-half-century.ts— the PL-diacriticWnetandPolwiektokens in EN body (§3c, 2 warnings) are resolved when the four-phase pick forpine-half-centurysettles the EN first-name form and surname translation.quest-004-polowa-rejestru.ts— three PL-diacriticWnetEN body warnings (§3c) are resolved mechanically after thepine-half-centurypick settles.quest-005-niemilknacy-kurier.ts— the quoted-dialog tokens (PL diacritics in Bertranda / Marno character-voice lines) and the quest-005 pending handle rename (§3d) can be addressed in a single Phase C pass.quest-006-najstarsze-biuro.ts— PL-diacriticKepkaEN body occurrences (§3c, 3 warnings) and the PL-diacritic era-namePomylka(§3c, 1 warning) are both in this file, which is also a pending handle rename (§3d). One pass resolves all four issues plus the handle rename.
In general: for quests 002-006, the Phase C rename pass that converts the PL slug handle to an EN handle also creates the opportunity to sweep the EN body strings in the same commit, minimising file-churn.
4. Phase C work breakdown (ordered tasks for narrative-designer)
Tasks are ordered with dependency-first sequencing. Four-phase picks (narrative-designer Opus) must precede mechanical sweeps (narrative-ops Sonnet) that depend on the picked EN form.
handle: drobnogórze-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry added)acceptance: glossary entry for bare handle "drobnogórze" with kind:place, pl==en, transcreationNote covers toponym-preservation rule; pnpm lint:naming passes for bound-soot.ts:15 and frostlands-honey.ts:15source: §3c, bound-soot.ts + frostlands-honey.tsstatus: todohandle: pieczetarnia-mroza-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry added)acceptance: glossary entry for "pieczetarnia-mroza" with kind:place, pl==en, transcreationNote; pnpm lint:naming passes for frost-thing-slow-vent.ts:16source: §3c, frost-thing-slow-vent.tsstatus: todohandle: pomylka-era-name-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry) + data/src/content/quests/quest-006-najstarsze-biuro.ts (EN body edit or authorised-loanword exemption)acceptance: CEO picks translation vs preservation; glossary entry created; quest-006:68 warning resolvedsource: §3c, quest-006:68; §5 Q3status: blocked-ceo (§5 Q3)handle: pieczetarka-loanword-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry)acceptance: glossary entry for "pieczetarka" with kind:loanword and an EN translation (e.g. "seal-clerk"); narrative-designer confirms EN term; entry passes lintsource: §3c, quest-003:58,66status: needs-narrative-designer-en-pickhandle: urzednik-loanword-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry)acceptance: glossary entry for "urzednik" with kind:loanword, EN translation (e.g. "gate official"); narrative-designer confirmssource: §3c, quest-005:73status: needs-narrative-designer-en-pickhandle: krok-loanword-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry)acceptance: glossary entry for "krok" with kind:loanword, EN translation (e.g. "pace" or "stride"); narrative-designer confirms canonical EN unit name; quest-005:112 passessource: §3c, quest-005:112status: needs-narrative-designer-en-pickhandle: dom-pod-wczesna-pieczecia-glossary-entrykind: glossary-entryscope: data/src/content/_glossary.ts (1 entry)acceptance: glossary entry for "dom-pod-wczesna-pieczecia" with kind:place; EN form decided (preserve PL proper-noun or translate); quest-006:130 passessource: §3c, quest-006:130status: needs-narrative-designer-en-pickhandle: janislaw-en-body-sweepkind: mechanical-editscope: data/src/content/npcs/kepka-witness-bookkeeper.ts (replace Janisław with Janislaw in description.en)acceptance: kepka-witness-bookkeeper.ts:22 lint warning resolved; no other file affected (other EN body uses already use diacritic-free form)source: §3c, kepka-witness-bookkeeper.ts:22status: todo (no pick needed; diacritic-stripped form is canonical per three-receipts glossary entry)handle: quoted-pl-dialog-ceo-decisionkind: ceo-callscope: see §5 Q2acceptance: CEO rules on glossed-EN-with-parenthetical vs strict-anglicise for all five quoted-dialog tokens; decision recordedsource: §3c (5 quoted-dialog warnings across stary-marno-niedoczas.ts, quest-004.ts, quest-005.ts x2, quest-006.ts)status: blocked-ceo (§5 Q2)handle: full-sentence-elder-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts (update transcreationNote, confirm or replace EN handle); data/src/content/npcs/full-sentence-elder.ts if EN handle changesacceptance: PENDING_PHASE_C_PICK marker removed; four-phase provenance confirmed; pnpm lint:naming handle-in-glossary stays at 0source: §3d, full-sentence-elderstatus: todohandle: stary-marno-niedoczas-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts (new EN handle, remove PENDING marker); data/src/content/npcs/stary-marno-niedoczas.ts (id rename); all files that reference npc.stary-marno-niedoczasacceptance: PENDING_PHASE_C_PICK removed; EN handle chosen from candidates; id in entity file updated; cross-references updated; if quoted-dialog decision is made (§5 Q2), stary-marno-niedoczas.ts:23 also resolvedsource: §3d; §3c (overlapping quoted-dialog warning)status: blocked-ceo (§5 Q2 first for dialog sweep)handle: brodek-spozniony-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; data/src/content/npcs/brodek-spozniony.ts (id rename); cross-referencesacceptance: PENDING_PHASE_C_PICK removed; EN handle chosen; file renamed if CEO picks option (a) or (c) for quest prefix (not applicable here — NPC files do not have the prefix issue, so rename is unconditional)source: §3dstatus: todohandle: pan-bezelec-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; data/src/content/npcs/pan-bezelec.ts (id rename); cross-referencesacceptance: PENDING_PHASE_C_PICK removed; EN handle chosen from candidatessource: §3dstatus: todohandle: kepka-witness-bookkeeper-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; data/src/content/npcs/kepka-witness-bookkeeper.ts (id, name.en); all EN body occurrences of Kępka in quest-006 (5 occurrences)acceptance: PENDING_PHASE_C_PICK removed; EN handle fully EN; kepka-witness-bookkeeper.ts:12 warning resolved; quest-006 Kępka sweep completesource: §3d + §3c (kepka-witness-bookkeeper.ts:12; quest-006:47,84,108)status: todohandle: pine-half-century-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; data/src/content/npcs/pine-half-century.ts (name.en, id if handle changes); all EN body occurrences of Wnęt across quest-004 (3 occurrences) and pine-half-century.ts; Półwiek quoted reference in pine-half-century description.enacceptance: PENDING_PHASE_C_PICK removed; pine-half-century.ts:11,22 resolved; quest-004:68,85,106 resolvedsource: §3d + §3c (pine-half-century.ts:11,22; quest-004:68,85,106)status: todohandle: quest-002-handle-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts (update handle, remove PENDING marker); data/src/content/quests/quest-002-pieczetarnia-milczy.ts (id field; filename under CEO option a/c); all prerequisites referencing quest.002-pieczetarnia-milczyacceptance: PENDING_PHASE_C_PICK removed; EN handle chosen; prerequisite references updated; filename resolved per CEO optionsource: §3d; §3astatus: blocked-ceo (§5 Q1 for filename option)handle: quest-003-handle-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; quest-003 file (id + filename option); pieczętarka EN body sweep (2 warnings in same file, done in same pass); prerequisite referencesacceptance: PENDING_PHASE_C_PICK removed; quest-003:58,66 resolved; filename resolved per CEO optionsource: §3d + §3c (quest-003:58,66); §3astatus: blocked-ceo (§5 Q1) + needs pieczetarka loanword entry firsthandle: quest-004-handle-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; quest-004 file (id + filename option); Wnęt sweep in quest-004 (after pine-half-century pick); pójdziesz quoted-dialog (after CEO Q2); prerequisite referencesacceptance: PENDING_PHASE_C_PICK removed; filename resolved; quest-004:68,85,106 resolved (after pine-half-century pick); quest-004:29 resolved (after CEO Q2)source: §3d + §3c (quest-004:29,68,85,106); §3astatus: blocked-ceo (§5 Q1 + Q2) + depends on pine-half-century pickhandle: quest-005-handle-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; quest-005 file (id + filename option); urzednik EN sweep; krok EN sweep; quoted-dialog sweep (after CEO Q2); prerequisite referencesacceptance: PENDING_PHASE_C_PICK removed; quest-005:73,112 resolved; quest-005:90,138 resolved (after CEO Q2); filename resolvedsource: §3d + §3c (quest-005:73,90,112,138); §3astatus: blocked-ceo (§5 Q1 + Q2) + depends on urzednik and krok loanword entrieshandle: quest-006-handle-four-phase-pickkind: four-phase-pickscope: data/src/content/_glossary.ts; quest-006 file (id + filename option); Kępka sweep (after kepka pick); Pomyłka resolution (after CEO Q3); dom-pod-wczesna-pieczecia entry; idę quoted-dialog (after CEO Q2); prerequisite referencesacceptance: PENDING_PHASE_C_PICK removed; quest-006:47,68,84,108,130 resolved; idę warning resolved; filename resolvedsource: §3d + §3c (quest-006:18,47,68,84,108,130); §3astatus: blocked-ceo (§5 Q1 + Q2 + Q3) + depends on kepka pick + dom-pod-wczesna-pieczecia entryTask count summary: 20 tasks total (7 glossary-entry tasks, 1 mechanical EN body edit, 1 CEO call, 11 four-phase picks). Of the 11 picks, 6 are NPC picks and 5 are quest handle picks. Dependency graph: CEO decisions in §5 unblock the quoted-dialog tasks and the filename option; glossary entries for loanwords unblock the quest handle sweeps; NPC four-phase picks unblock EN body sweeps in quest files that reference those NPCs.
5. Open questions for CEO
Q1 — Quest filename prefix divergence (§3a)
The quest-NNN- prefix in all six quest filenames causes the filename-matches-handle rule to fire for all six. Three options:
- (a) Rename quest files to drop prefix.
quest-001-first-road.ts→001-first-road.ts. Zero lint code change. Real cost: file-tree readability lost; all JSDoc cross-references to quest file paths by name must be swept (at least 12 occurrences across data files referencing each other in headers); every future quest authored without the prefix loses the self-documenting convention. - (b) Strip ordinal from id-handle.
quest.001-first-road→quest.first-road. Still does not fix the filename mismatch without also renaming; loses canonical quest ordering from the id itself. Strictly worse than (a). - (c) Update lint rule to recognise
quest-NNN-prefix as canonical for the quest schema kind. Two-line script change inscripts/lint-naming.mjs. No content, no id, no file renamed. Tooling adapts to an established and useful convention.
Recommendation: (c). The prefix is ergonomic and correct; the lint rule should be kind-aware. If CEO prefers (a), qa-engineer will scope the cross-reference sweep before Phase C executes it.
Q2 — Quoted PL dialog in EN body strings
Five quoted PL lines appear in EN body fields: Bertranda’s go-look-return instruction, and four Marno lines (I-walk-and-live-by-it, I-know-your-ring, thank-you-for-not-slowing, and the central do-not-ask-who-I-am-going-to sentence). These are canonical character-voice lines whose register (formal Polish, flat delivery, incomplete sentences) is diegetically significant.
- (a) Strict anglicise. Replace PL quoted forms with EN translation only. Lint passes. Flavour loss: the PL quoted form is what the player sees in the game EN build; removing it makes the character speak standard English rather than a character with a distinct diegetic voice.
- (b) Glossed EN with parenthetical PL original. Append an EN gloss immediately after the PL quote in the same string. The PL form is preserved inline as flavour; the EN gloss follows. Lint rule may need a
glossed-inlineexemption pattern, or the quoted PL can be moved to aflavourfield (which is separate from thedescription.enbody the rule scans). This preserves the diegetic register at the cost of a small lint-rule extension. - (c) Move quoted PL to
flavourfield only. Theendescription body uses EN-only narration; the original PL quote lives inflavour.enas the canonical character-voice artefact. Lint rule does not scanflavourfields (confirm with tech-architect). Clean separation; no lint extension needed.
Recommendation: (b) if the lint rule can be extended to allow inline-glossed PL quotes. (c) if rule extension is too costly. This is a flavour-loss tradeoff that is the CEO’s call — the audit surfaces it, does not decide it.
Q3 — pomylka era-name treatment in EN body
The PL-diacritic era name Pomylka (handle: pomylka) appears in the quest-006 beat-2 brass-plate text. It is the canonical era-marking event name used on dated plaques throughout Plenny. Two options:
- (a) Toponym-preservation. Register
pomylkaas a proper-noun era name in the glossary (kind: place,pl == en), making it an authorised loanword in EN body. The EN description keeps"Year 33 after Pomylka"(PL form as proper noun, analogous to howPlenny,Targosie, andMglicaare preserved). - (b) Anglicise. Register as loanword with EN form
"the Mistake". EN body reads"Year 33 after the Mistake". Cleaner for EN players; loses the in-world linguistic texture of a city that dates years in its own language even on brass plaques.
Recommendation: (a), for internal consistency with the toponym-preservation rule. The PL era-name form functions as an era-name-as-proper-noun the same way “Anno Domini” functions in English — the PL form IS the canonical reference, not a translation of it. CEO to confirm.
6. Acceptance criteria for Phase C completion
Phase C is complete when ALL of the following pass:
-
pnpm lint:namingtotal warnings: 0. Zero warnings under all three rules. The only permitted exception is a documented exemption registered inscripts/lint-naming.mjscomments (e.g. if CEO selects option (c) for quest prefix, the rule is updated to emit 0 rather than 6 warnings; that counts as 0). -
data/src/content/_glossary.tshas zeroPENDING_PHASE_C_PICKmarkers. Grep:grep -r "PENDING_PHASE_C_PICK" data/src/content/_glossary.tsreturns empty. All 11 pending entries have been resolved with a completed four-phase pick; each entry has atranscreationNotethat documents the pick rationale without the pending token. -
All quest file slugs match their bare handles under whichever resolution CEO picks. If option (a): filenames
001-*.tsthrough006-*.ts. If option (c): lint rule updated, filenames unchanged, rule passes at 0. Verified by runningpnpm lint:namingwith nofilename-matches-handlewarnings. -
All entity file IDs reference handles that exist in the glossary.
pnpm lint:namingrulehandle-in-glossaryat 0. Already at 0; Phase C must not regress this by adding new entity files without glossary entries. -
All EN body strings either pass the diacritic check or reference a glossary entry that authorises the token.
pnpm lint:namingruleen-body-no-untracked-plat 0. This requires: (a) all loanword glossary entries added, (b) all EN body strings updated or authorised, (c) all quoted-dialog warnings resolved per CEO Q2 decision, (d) all hybrid-name EN body occurrences updated after four-phase picks complete. -
pnpm lint:languagepasses. The new glossary entries and EN body edits must not introduce PL text into ENG-only paths or vice versa. Runpnpm lint:languageafter each Phase C commit batch. -
pnpm lint:tagspasses. No Phase C action is expected to touch wiki pages, but any wiki edits (e.g. lore pages referencing renamed quest handles) must carry valid frontmatter tags. -
pnpm --filter @walkrpg/data typecheckpasses. Schema validation still passes after all entity file id-renames (id field must remain valid perQuestIdSchema,NpcIdSchema, etc.). -
Cross-reference integrity. Any entity file that lists another in its
prerequisitesarray (quests) or JSDoc header must reference the current id/handle post-rename. Grep for the old PL handles in alldata/src/content/files and confirm 0 stale references after each rename batch.
Stop-flag-ask findings
The following were observed during the audit that are outside the scope of the three lint rules and D-017, and require routing before Phase C acts:
SF-1 — kepka-witness-bookkeeper.ts uses the PL-diacritic form of a first name in description.en (line 83) but the diacritic-free transliteration in role.en (line 79). The inconsistency is within a single EN body. The lint catches the diacritic occurrence in description.en. Phase C can fix this mechanically (replace the PL-diacritic form with the diacritic-stripped transliteration in description.en), but the presence of an inconsistency suggests the EN body sweep for NPC first names that appear in other NPC descriptions needs to be systematic, not piecemeal. Routing to: qa-engineer can handle the mechanical sweep; no CEO input needed, but narrative-ops Sonnet should run a grep for all first-name diacritics in EN body fields after the four-phase picks resolve.
SF-2 — quest-006-najstarsze-biuro.ts beat-2 uses a direct PL plaque quotation inside an EN body string. The plaque text includes WOLNOKUPIECTWO TARGOSIE — Biuro Najstarsze, 33 r. po Pomylce (PL with one diacritic flagged). The lint fires only on the diacritic character, missing the WOLNOKUPIECTWO TARGOSIE — Biuro Najstarsze portion (no diacritics in those words, but they are PL institutional names). This means the lint rule’s diacritic-detection heuristic does not catch PL text that happens to use only ASCII characters. This is a gap in the rule’s coverage — a broader approach (e.g. detecting known PL institutional names in EN body strings) would require a significant lint rule expansion. Flagged here for tech-architect or qa-engineer review of the lint rule scope; not a Phase C content task.
SF-3 — RESOLVED (false alarm; system-reviewer cross-check confirmed). The entity file data/src/content/npcs/full-sentence-elder.ts exists; line 9 carries id: NpcIdSchema.parse("npc.full-sentence-elder"). The handle is correctly registered in the glossary AND the entity file is on disk. The PENDING_PHASE_C_PICK marker stands for four-phase provenance verification only (the handle reads clean but its derivation is undocumented in the 18.05 decision) — Phase C still owes a verification pass, but there is no missing-file gap. No routing action required.