Renames all dialogue and monologue line IDs from location-scoped (the-terminal_d_039) to NPC-scoped (kael-davan_d_001) format per D-035 Sprint 15 amendment
Covers 20 dialogue pool files (3 locations) and 14 monologue pool files (detective + smuggler)
Fixes cross-file duplicate IDs for multi-location NPCs: kael-davan (3 locations, 75 total lines), pc-detective and pc-smuggler (2 locations each, 8 lines each) get globally unique continuous sequences
Zero content changes — pure ID substitution. The old location-scoped scheme already caused a collision (the-terminal_d_039 in two files) and would not scale to procedurally generated populations (D-029).
Pre-PR notes
make pre-pr-validate passes for all dialogue/monologue content (0 new errors)
Remaining validation errors (9 unknown fact_id references in NPC profiles, npc_count mismatch) are pre-existing issues outside this ticket's scope
make pre-pr-lint fails on pre-existing Rust clippy issues in server/ — not introduced by this change (all 45 changed files are content/docs)
Test plan
make pre-pr-validate shows no dialogue ID duplicates or schema errors
grep for _d_0[0-9][0-9][0-9] in dialogue files confirms NPC-slug prefixes only
## Summary
- Renames all dialogue and monologue line IDs from location-scoped (`the-terminal_d_039`) to NPC-scoped (`kael-davan_d_001`) format per D-035 Sprint 15 amendment
- Covers 20 dialogue pool files (3 locations) and 14 monologue pool files (detective + smuggler)
- Fixes cross-file duplicate IDs for multi-location NPCs: kael-davan (3 locations, 75 total lines), pc-detective and pc-smuggler (2 locations each, 8 lines each) get globally unique continuous sequences
- Updates schema description fields, NPC authoring style guide, and design/workshop docs
Zero content changes — pure ID substitution. The old location-scoped scheme already caused a collision (`the-terminal_d_039` in two files) and would not scale to procedurally generated populations (D-029).
## Pre-PR notes
- `make pre-pr-validate` passes for all dialogue/monologue content (0 new errors)
- Remaining validation errors (9 unknown `fact_id` references in NPC profiles, npc_count mismatch) are pre-existing issues outside this ticket's scope
- `make pre-pr-lint` fails on pre-existing Rust clippy issues in `server/` — not introduced by this change (all 45 changed files are content/docs)
## Test plan
- [ ] `make pre-pr-validate` shows no dialogue ID duplicates or schema errors
- [ ] grep for `_d_0[0-9][0-9][0-9]` in dialogue files confirms NPC-slug prefixes only
- [ ] Multi-location NPC sequences are globally unique (kael-davan 001–075, pc-detective 001–008, pc-smuggler 001–008)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Line IDs in all dialogue and monologue pool files renamed from the
old location-scoped format (e.g. the-terminal_d_039) to the new
NPC-scoped format (e.g. kael-davan_d_001) per the D-035 Sprint 15
amendment.
Changes:
- 20 dialogue pool files across 3 locations renamed
- 14 monologue pool files (detective + smuggler) renamed
- Schema descriptions updated in dialogue/monologue schema files
- Authoring style guide and design docs updated with new examples
- Multi-location NPCs (kael-davan, pc-detective, pc-smuggler) given
globally unique cross-file sequences to satisfy XREF uniqueness check
The location-scoped scheme already caused a collision (the-terminal_d_039
appearing in multiple NPC files) and would not scale to procedurally
generated NPC populations (D-029). Zero content changes — pure ID
substitution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Review: copy -> main (type: copy) — APPROVED with notes
Three reviewers (Hoshe QA, Paula narrative, Miri world consistency) reviewed 46 changed files.
Summary
The mechanical line ID migration is correct: all 20 dialogue files and 14 monologue files use NPC-scoped IDs, no old location-slug format survives, and multi-location NPC sequences are globally unique (kael-davan 001-075 across 3 files, pc-detective and pc-smuggler 001-008 across 2 files each). No dialogue text, tags, or dual_lens entries were changed. Schema descriptions and authoring docs updated.
Notes for follow-up (not blocking merge)
Documentation stale examples (3 warnings):
docs/architecture/line-pool-format.md Section 3.5: worked example shows kael-davan_d_001 at the-last-shift (should be _d_015 after renumbering)
docs/architecture/line-pool-format.md Section 5.1: "Sequence restarts at _001 per file" note contradicts multi-location implementation
content/_meta/npc-authoring-style-guide.md Section 16: worked example uses role-scoped ID dock-worker_d_071 while citing NPC-scoped compliance
Stale mood vocabulary (3 warnings, pre-existing):
docs/architecture/line-pool-format.md Section 6.5, docs/design/content-directory-structure.md Appendix B, and content/_meta/npc-authoring-style-guide.md Section 11 all list pre-Sprint 14 mood values
Monologue ID uniqueness (noted, deferred):
Monologue files restart at _001 per file (composite key design). Registered Q-028 + ticket #544 for collision-resistant IDs for auto-generated NPCs.
Minor (suggestions):
bar-owner.yaml line 3: comment says "Lera Osk" — canonical is "Lera Sessik"
sera-venn.yaml line 17: header cross-reference off by 2 lines
## Review: copy -> main (type: copy) — APPROVED with notes
Three reviewers (Hoshe QA, Paula narrative, Miri world consistency) reviewed 46 changed files.
### Summary
The mechanical line ID migration is correct: all 20 dialogue files and 14 monologue files use NPC-scoped IDs, no old location-slug format survives, and multi-location NPC sequences are globally unique (kael-davan 001-075 across 3 files, pc-detective and pc-smuggler 001-008 across 2 files each). No dialogue text, tags, or dual_lens entries were changed. Schema descriptions and authoring docs updated.
### Notes for follow-up (not blocking merge)
**Documentation stale examples (3 warnings):**
- `docs/architecture/line-pool-format.md` Section 3.5: worked example shows `kael-davan_d_001` at the-last-shift (should be `_d_015` after renumbering)
- `docs/architecture/line-pool-format.md` Section 5.1: "Sequence restarts at _001 per file" note contradicts multi-location implementation
- `content/_meta/npc-authoring-style-guide.md` Section 16: worked example uses role-scoped ID `dock-worker_d_071` while citing NPC-scoped compliance
**Stale mood vocabulary (3 warnings, pre-existing):**
- `docs/architecture/line-pool-format.md` Section 6.5, `docs/design/content-directory-structure.md` Appendix B, and `content/_meta/npc-authoring-style-guide.md` Section 11 all list pre-Sprint 14 mood values
**Monologue ID uniqueness (noted, deferred):**
- Monologue files restart at _001 per file (composite key design). Registered Q-028 + ticket #544 for collision-resistant IDs for auto-generated NPCs.
**Minor (suggestions):**
- `bar-owner.yaml` line 3: comment says "Lera Osk" — canonical is "Lera Sessik"
- `sera-venn.yaml` line 17: header cross-reference off by 2 lines
Content validation: 0 schema errors, 0 new cross-ref errors (9 pre-existing fact_id errors, 21 pre-existing relationship warnings).
Tests run: Manual inspection of all changed files plus targeted grep passes
Verdict: REQUEST_CHANGES
Verdict: REQUEST_CHANGES
One critical issue, two warnings, three suggestions. The migration is mostly correct — 37 of 40 content files follow the NPC-scoped format without problems. The critical issue is two surviving old-format ID references in unchanged files that reference renamed IDs. The blocking issue is in docs/architecture/line-pool-format.md, which is a changed file in this PR with a stale mood vocabulary table that is now actively wrong documentation for authors consulting it after merge.
Summary
The mechanical ID rename is correctly applied across all 20 dialogue pool files and 14 monologue pool files. All new IDs match the {npc-slug}_{d|m}_{###} and {npc-slug}_m_{s|d}_{###} patterns. No old location-scoped IDs (the-terminal_d_xxx, the-last-shift_d_xxx) survive in the renamed content files. Multi-location NPC sequences (kael-davan, pc-detective, pc-smuggler) are globally unique and continuous across their location files, which matches the intent stated in the PR description. Schema descriptions are updated. Authoring style guide is updated.
Two orphaned old-format references survive in files not included in this PR's diff. Since line-pool-format.md is a changed file in this PR, the stale mood vocabulary in Section 6.5 is now actively misleading documentation that this PR is in a position to fix.
Failures
CRITICAL: docs/architecture/line-pool-format.md Section 6.5 — Stale mood vocabulary
These are the pre-Sprint 14 mood values. The Sprint 14 amendment to D-035 renamed the mood vocabulary. The current schemas (dialogue-pool.schema.json, monologue-pool.schema.json) and all YAML content files use:
This is a changed file in PR #59. An author consulting this document post-merge would be given vocabulary that fails schema validation. The correct values are already in the schemas and are confirmed by every mood tag in the YAML files in this PR.
Expected: Section 6.5 lists anxious, frustrated, content, suspicious, warm, hostile, relieved, focused with a note referencing the Sprint 14 amendment.
Actual: Section 6.5 lists the pre-Sprint 14 vocabulary.
Reproduction: Open docs/architecture/line-pool-format.md Section 6.5 and compare to content/_schema/dialogue-pool.schema.jsonmood.items.enum.
WARNING: Orphaned old-format ID reference in maintenance-tech.yaml comment
# KEY LINE: the-terminal_d_040 — sounds like surveillance knowledge, is a maintenance complaint
The ID the-terminal_d_040 is the old location-scoped format. After this migration, the maintenance-tech NPC's first line is maintenance-tech_d_001. The comment refers to a line that no longer exists under that ID. This is a stale reference that will cause confusion for authors and reviewers looking up line IDs.
Expected: Comment references the new ID (maintenance-tech_d_001 or simply describes the line without citing an ID).
don't reconcile. Cross-ref: Kael dialogue the-terminal_d_008
("Manifest says this one's forty kilos over") and the-terminal_d_018
Both the-terminal_d_008 and the-terminal_d_018 are old location-scoped IDs. After this migration, Kael's terminal dialogue lines are kael-davan_d_034 through kael-davan_d_075. The referenced lines are now kael-davan_d_041 ("Manifest says this one's forty kilos over") and the courier line that was formerly the-terminal_d_018.
Note: This file was not included in the PR diff, so this may be a separate ticket. However, PR #59 creates a broken cross-reference in content that was valid before merge. The migration introduced the breakage; the fix should accompany it or be tracked explicitly.
Suggestions (non-blocking)
SUGGESTION: docs/architecture/line-pool-format.md Section 3.5 worked example uses stale IDs
- id:kael-davan_d_001text:"Saved you a seat. Lera's got the spiced rice tonight."
After this migration, kael-davan_d_001 is in maintenance-corridors/kael-davan.yaml ("Package is in the junction locker"). The last-shift greeting is now kael-davan_d_015. The example still compiles and the ID format is correct — the issue is only that the example ID no longer matches the actual text in the YAML. This confuses authors cross-referencing the docs against content.
Similarly, the same section example shows kael-davan_d_010 and kael-davan_d_012 with last-shift content, but the actual last-shift file now starts at _d_015.
This is a "should fix" rather than a blocker.
SUGGESTION: docs/architecture/line-pool-format.md Section 5.3 — "Sequence restarts at _001 per file" note
Sequence restarts at _001 per file; IDs are unique within a file.
This contradicts the actual implementation for multi-location NPCs. Kael Davan's sequences are:
maintenance-corridors/kael-davan.yaml: _d_001 through _d_014
the-last-shift/kael-davan.yaml: _d_015 through _d_033
the-terminal/kael-davan.yaml: _d_034 through _d_075
The sequences do not restart. The PR description explicitly describes this as intentional: "multi-location NPC sequences are globally unique continuous sequences." The spec note should be updated to reflect this: globally unique sequences per NPC, not per file. The current note will cause authors to incorrectly restart sequences at _001 for each location file, creating duplicate IDs within the same NPC namespace.
SUGGESTION: bar-owner.yaml header comment — NPC name inconsistency
File:content/campaigns/main/systems/krenn/stations/sova/districts/transit/dialogue/the-last-shift/bar-owner.yaml, line 3 Severity: Suggestion
The file header reads:
# NPC: Lera Osk (Tier 2, SYSTEM/OPERATOR)
D-036 canonical NPC naming and D-034 confirmed name is "Lera Sessik" (referenced in npc-authoring-style-guide.md Section 2, Tier 2 canonical list: "Lera Sessik (ANCHOR/OPERATOR)"). The comment uses "Lera Osk" which does not match the canonical name. This is pre-existing but the file is included in this PR's diff.
Verification Passes
ID format compliance — PASS
All 20 dialogue files: every id: field matches ^[a-z][a-z0-9-]*_d_[0-9]{3}$. No old {location-slug}_d_{###} patterns found in any line id: field.
ID format compliance (monologue) — PASS
All 14 monologue files: every id: field matches ^[a-z][a-z0-9-]*_m_[sd]_[0-9]{3}$. All detective monologue uses _m_d_, all smuggler monologue uses _m_s_.
Within-file uniqueness — PASS
All ID sequences within each individual YAML file are unique. No duplicate IDs within any single file.
Multi-location NPC cross-file continuity — PASS
Verified three NPCs with content across multiple location files:
kael-davan: _d_001–_d_014 (maintenance-corridors), _d_015–_d_033 (the-last-shift), _d_034–_d_075 (the-terminal). Continuous, no gaps or overlaps.
Monologue restart-per-file pattern — PASS (by design)
Detective and smuggler monologue files each restart at _001 per file. This is correct per the (file_path, line_id) composite key design in line-pool-format.md Section 5.3. The apparent collisions (multiple files containing pc-detective_m_d_001) are intentional — the engine indexes by file path + ID, not by ID alone.
Zero content changes — PASS
No text:, access:, trust:, situation:, topic:, mood:, tags:, dual_lens:, notes:, or knowledge_grant: fields were modified. Pure ID substitution confirmed across all files.
Schema description updates — PASS
Both dialogue-pool.schema.json and monologue-pool.schema.json updated id field descriptions to reference NPC-scoped format. Regex patterns unchanged (prefix pattern ^[a-z][a-z0-9-]* already matched NPC slugs).
Cross-references in prerequisite blocks — PASS
All relationship.target values in monologue prerequisites use entity reference format (npc:kael-davan, npc:sera-venn) — these are not line IDs and were not subject to this migration. No prerequisite references use line IDs. No cross-file prerequisite breakage found.
Enum vocabulary in content files — PASS
All mood:, access:, trust:, situation:, topic: values in all 34 content YAML files match current schema enums. The Sprint 14 mood rename (warm not fond, content not comfortable, etc.) is consistently applied throughout.
Notes
The monologue per-file restart is correct. The composite key design means pc-detective_m_d_001 in the-terminal.yaml and pc-detective_m_d_001 in the-last-shift.yaml are different lines to the engine. This is not a bug. The note in line-pool-format.md Section 5.3 stating "IDs are not required to be globally unique — npc-slug + file path provides global uniqueness" confirms this. The confusion arises because the dialogue NPCs (kael-davan, pc-detective, pc-smuggler) use globally-unique continuous sequences, while the monologue PC files restart. Both are valid implementations of the spec; they just use different scoping strategies. The spec note "Sequence restarts at _001 per file" (Section 5.3) describes the monologue approach but is incorrect as a general statement because the dialogue multi-location NPCs do not restart.
Scope note: The critical line-pool-format.md Section 6.5 mood vocabulary issue must be fixed in this PR or before merge, since this PR touches that file and the stale content becomes the documented standard post-merge. All other items are non-blocking suggestions or notes for follow-up tickets.
## Test Report: PR #59 — Line ID Namespace Migration (D-035 Sprint 15)
- **Date:** 2026-02-23
- **Reviewer:** Hoshe (QA)
- **Spec reference:** D-035 (Amendment: Sprint 15), `docs/architecture/line-pool-format.md` Section 5
- **Files reviewed:** 46 changed files (20 dialogue YAML, 14 monologue YAML, 3 schemas, 9 docs/meta)
- **Tests run:** Manual inspection of all changed files plus targeted grep passes
- **Verdict:** REQUEST_CHANGES
---
## Verdict: REQUEST_CHANGES
**One critical issue, two warnings, three suggestions.** The migration is mostly correct — 37 of 40 content files follow the NPC-scoped format without problems. The critical issue is two surviving old-format ID references in unchanged files that reference renamed IDs. The blocking issue is in `docs/architecture/line-pool-format.md`, which is a changed file in this PR with a stale mood vocabulary table that is now actively wrong documentation for authors consulting it after merge.
---
## Summary
The mechanical ID rename is correctly applied across all 20 dialogue pool files and 14 monologue pool files. All new IDs match the `{npc-slug}_{d|m}_{###}` and `{npc-slug}_m_{s|d}_{###}` patterns. No old location-scoped IDs (`the-terminal_d_xxx`, `the-last-shift_d_xxx`) survive in the renamed content files. Multi-location NPC sequences (kael-davan, pc-detective, pc-smuggler) are globally unique and continuous across their location files, which matches the intent stated in the PR description. Schema descriptions are updated. Authoring style guide is updated.
Two orphaned old-format references survive in files not included in this PR's diff. Since `line-pool-format.md` is a changed file in this PR, the stale mood vocabulary in Section 6.5 is now actively misleading documentation that this PR is in a position to fix.
---
## Failures
### CRITICAL: `docs/architecture/line-pool-format.md` Section 6.5 — Stale mood vocabulary
**File:** `/docs/architecture/line-pool-format.md`
**Severity:** Critical
Section 6.5 "Moods (D-028 Layer 4)" lists:
```
fond, comfortable, worried, suspicious, analytical, conflicted, concerned, relieved
```
These are the pre-Sprint 14 mood values. The Sprint 14 amendment to D-035 renamed the mood vocabulary. The current schemas (`dialogue-pool.schema.json`, `monologue-pool.schema.json`) and all YAML content files use:
```
anxious, frustrated, content, suspicious, warm, hostile, relieved, focused
```
This is a changed file in PR #59. An author consulting this document post-merge would be given vocabulary that fails schema validation. The correct values are already in the schemas and are confirmed by every mood tag in the YAML files in this PR.
**Expected:** Section 6.5 lists `anxious`, `frustrated`, `content`, `suspicious`, `warm`, `hostile`, `relieved`, `focused` with a note referencing the Sprint 14 amendment.
**Actual:** Section 6.5 lists the pre-Sprint 14 vocabulary.
**Reproduction:** Open `docs/architecture/line-pool-format.md` Section 6.5 and compare to `content/_schema/dialogue-pool.schema.json` `mood.items.enum`.
---
### WARNING: Orphaned old-format ID reference in `maintenance-tech.yaml` comment
**File:** `content/campaigns/main/systems/krenn/stations/sova/districts/transit/dialogue/the-terminal/maintenance-tech.yaml` (line 4)
**Severity:** Warning
The comment at line 4 reads:
```
# KEY LINE: the-terminal_d_040 — sounds like surveillance knowledge, is a maintenance complaint
```
The ID `the-terminal_d_040` is the old location-scoped format. After this migration, the maintenance-tech NPC's first line is `maintenance-tech_d_001`. The comment refers to a line that no longer exists under that ID. This is a stale reference that will cause confusion for authors and reviewers looking up line IDs.
**Expected:** Comment references the new ID (`maintenance-tech_d_001` or simply describes the line without citing an ID).
**Actual:** Comment references orphaned `the-terminal_d_040`.
**Note:** This file is listed in the PR diff. The comment was not updated during the migration pass.
---
### WARNING: Orphaned old-format ID references in `smuggler-inventory.yaml` (not in diff)
**File:** `content/campaigns/main/systems/krenn/stations/sova/districts/transit/items/smuggler-inventory.yaml` (lines 50-51)
**Severity:** Warning
Lines 50-51 contain:
```
don't reconcile. Cross-ref: Kael dialogue the-terminal_d_008
("Manifest says this one's forty kilos over") and the-terminal_d_018
```
Both `the-terminal_d_008` and `the-terminal_d_018` are old location-scoped IDs. After this migration, Kael's terminal dialogue lines are `kael-davan_d_034` through `kael-davan_d_075`. The referenced lines are now `kael-davan_d_041` ("Manifest says this one's forty kilos over") and the courier line that was formerly `the-terminal_d_018`.
**Note:** This file was not included in the PR diff, so this may be a separate ticket. However, PR #59 creates a broken cross-reference in content that was valid before merge. The migration introduced the breakage; the fix should accompany it or be tracked explicitly.
---
## Suggestions (non-blocking)
### SUGGESTION: `docs/architecture/line-pool-format.md` Section 3.5 worked example uses stale IDs
**File:** `docs/architecture/line-pool-format.md`, Section 3.5
**Severity:** Suggestion
The worked example in Section 3.5 shows:
```yaml
- id: kael-davan_d_001
text: "Saved you a seat. Lera's got the spiced rice tonight."
```
After this migration, `kael-davan_d_001` is in `maintenance-corridors/kael-davan.yaml` ("Package is in the junction locker"). The last-shift greeting is now `kael-davan_d_015`. The example still compiles and the ID format is correct — the issue is only that the example ID no longer matches the actual text in the YAML. This confuses authors cross-referencing the docs against content.
Similarly, the same section example shows `kael-davan_d_010` and `kael-davan_d_012` with last-shift content, but the actual last-shift file now starts at `_d_015`.
This is a "should fix" rather than a blocker.
### SUGGESTION: `docs/architecture/line-pool-format.md` Section 5.3 — "Sequence restarts at _001 per file" note
**File:** `docs/architecture/line-pool-format.md`, Section 5.3
**Severity:** Suggestion
Section 5.3 states:
> Sequence restarts at `_001` per file; IDs are unique within a file.
This contradicts the actual implementation for multi-location NPCs. Kael Davan's sequences are:
- `maintenance-corridors/kael-davan.yaml`: `_d_001` through `_d_014`
- `the-last-shift/kael-davan.yaml`: `_d_015` through `_d_033`
- `the-terminal/kael-davan.yaml`: `_d_034` through `_d_075`
The sequences do not restart. The PR description explicitly describes this as intentional: "multi-location NPC sequences are globally unique continuous sequences." The spec note should be updated to reflect this: globally unique sequences per NPC, not per file. The current note will cause authors to incorrectly restart sequences at `_001` for each location file, creating duplicate IDs within the same NPC namespace.
### SUGGESTION: `bar-owner.yaml` header comment — NPC name inconsistency
**File:** `content/campaigns/main/systems/krenn/stations/sova/districts/transit/dialogue/the-last-shift/bar-owner.yaml`, line 3
**Severity:** Suggestion
The file header reads:
```
# NPC: Lera Osk (Tier 2, SYSTEM/OPERATOR)
```
D-036 canonical NPC naming and D-034 confirmed name is "Lera Sessik" (referenced in `npc-authoring-style-guide.md` Section 2, Tier 2 canonical list: "Lera Sessik (ANCHOR/OPERATOR)"). The comment uses "Lera Osk" which does not match the canonical name. This is pre-existing but the file is included in this PR's diff.
---
## Verification Passes
**ID format compliance — PASS**
All 20 dialogue files: every `id:` field matches `^[a-z][a-z0-9-]*_d_[0-9]{3}$`. No old `{location-slug}_d_{###}` patterns found in any line `id:` field.
**ID format compliance (monologue) — PASS**
All 14 monologue files: every `id:` field matches `^[a-z][a-z0-9-]*_m_[sd]_[0-9]{3}$`. All detective monologue uses `_m_d_`, all smuggler monologue uses `_m_s_`.
**Within-file uniqueness — PASS**
All ID sequences within each individual YAML file are unique. No duplicate IDs within any single file.
**Multi-location NPC cross-file continuity — PASS**
Verified three NPCs with content across multiple location files:
- `kael-davan`: `_d_001`–`_d_014` (maintenance-corridors), `_d_015`–`_d_033` (the-last-shift), `_d_034`–`_d_075` (the-terminal). Continuous, no gaps or overlaps.
- `pc-detective`: `_d_001`–`_d_003` (the-last-shift), `_d_004`–`_d_008` (the-terminal). Continuous.
- `pc-smuggler`: `_d_001`–`_d_003` (the-last-shift), `_d_004`–`_d_008` (the-terminal). Continuous.
**Monologue restart-per-file pattern — PASS (by design)**
Detective and smuggler monologue files each restart at `_001` per file. This is correct per the `(file_path, line_id)` composite key design in `line-pool-format.md` Section 5.3. The apparent collisions (multiple files containing `pc-detective_m_d_001`) are intentional — the engine indexes by file path + ID, not by ID alone.
**Zero content changes — PASS**
No `text:`, `access:`, `trust:`, `situation:`, `topic:`, `mood:`, `tags:`, `dual_lens:`, `notes:`, or `knowledge_grant:` fields were modified. Pure ID substitution confirmed across all files.
**Schema description updates — PASS**
Both `dialogue-pool.schema.json` and `monologue-pool.schema.json` updated `id` field descriptions to reference NPC-scoped format. Regex patterns unchanged (prefix pattern `^[a-z][a-z0-9-]*` already matched NPC slugs).
**Cross-references in prerequisite blocks — PASS**
All `relationship.target` values in monologue prerequisites use entity reference format (`npc:kael-davan`, `npc:sera-venn`) — these are not line IDs and were not subject to this migration. No prerequisite references use line IDs. No cross-file prerequisite breakage found.
**Enum vocabulary in content files — PASS**
All `mood:`, `access:`, `trust:`, `situation:`, `topic:` values in all 34 content YAML files match current schema enums. The Sprint 14 mood rename (`warm` not `fond`, `content` not `comfortable`, etc.) is consistently applied throughout.
---
## Notes
**The monologue per-file restart is correct.** The composite key design means `pc-detective_m_d_001` in `the-terminal.yaml` and `pc-detective_m_d_001` in `the-last-shift.yaml` are different lines to the engine. This is not a bug. The note in `line-pool-format.md` Section 5.3 stating "IDs are not required to be globally unique — npc-slug + file path provides global uniqueness" confirms this. The confusion arises because the dialogue NPCs (kael-davan, pc-detective, pc-smuggler) use globally-unique continuous sequences, while the monologue PC files restart. Both are valid implementations of the spec; they just use different scoping strategies. The spec note "Sequence restarts at _001 per file" (Section 5.3) describes the monologue approach but is incorrect as a general statement because the dialogue multi-location NPCs do not restart.
**Scope note:** The critical `line-pool-format.md` Section 6.5 mood vocabulary issue must be fixed in this PR or before merge, since this PR touches that file and the stale content becomes the documented standard post-merge. All other items are non-blocking suggestions or notes for follow-up tickets.
PR: feat(content): migrate line IDs to NPC-scoped namespace (D-035)
Hoshe (QA): REQUEST_CHANGES
The ID migration is mechanically sound across all YAML files. However:
#
File
Severity
Issue
1
docs/architecture/line-pool-format.md §6.5
critical
Mood vocabulary lists pre-Sprint-14 values (fond, comfortable, worried, etc.) — merging this makes stale vocabulary the documented standard. Authors consulting §6.5 get 8 values, 7 of which fail schema validation.
2
content/_meta/npc-authoring-style-guide.md §11
warning
Same stale mood vocabulary. File was partially updated by this PR but §11 was missed.
3
dialogue/the-terminal/maintenance-tech.yaml
warning
Orphaned the-terminal_d_040 ID (old format) may have been missed in the rename.
Paula (Narrative Depth): APPROVE
Clean migration. New NPC-scoped IDs are a genuine improvement for authoring clarity. No dialogue or monologue text was altered. Cross-character prerequisite references are stable. Flags the same mood vocabulary issues as warnings (items 1-2 above) and notes opening-hook-content.md has pre-existing design doc drift.
Miri (World Consistency): REQUEST_CHANGES
Thorough world consistency check. IP originality and lore are clean. Three substantive issues:
#
File
Severity
Issue
1
PC monologue files (all locations)
critical
Namespace collision — pc-detective_m_d_001 exists in the-terminal.yaml, the-last-shift.yaml, maintenance-corridors.yaml, AND opening.yaml. Four distinct lines with identical IDs. Engine will silently overwrite or error. Two resolution options: (A) location prefix in ID like pc-detective_m_d_term_001, or (B) reserved number ranges per file.
fact_id: location.surveillance_gaps should be investigation.surveillance_gaps per the knowledge vocabulary doc. Mismatched namespace means detective prerequisite gates will never fire from this grant.
Verdict: CHANGES REQUESTED
2 critical issues must be resolved before merge:
Mood vocabulary in line-pool-format.md §6.5 and style guide §11 — mechanical fix, update to post-Sprint-14 values (anxious, frustrated, content, suspicious, warm, hostile, relieved, focused)
PC monologue ID collision — all PC monologue files share pc-detective_m_d_001 / pc-smuggler_m_s_001 across locations. Schema design question that needs a decision before the migration is finalized.
## Review: copy (PR #59) → main — type: copy
PR: feat(content): migrate line IDs to NPC-scoped namespace (D-035)
### Hoshe (QA): REQUEST_CHANGES
The ID migration is mechanically sound across all YAML files. However:
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `docs/architecture/line-pool-format.md` §6.5 | **critical** | Mood vocabulary lists pre-Sprint-14 values (`fond`, `comfortable`, `worried`, etc.) — merging this makes stale vocabulary the documented standard. Authors consulting §6.5 get 8 values, 7 of which fail schema validation. |
| 2 | `content/_meta/npc-authoring-style-guide.md` §11 | warning | Same stale mood vocabulary. File was partially updated by this PR but §11 was missed. |
| 3 | `dialogue/the-terminal/maintenance-tech.yaml` | warning | Orphaned `the-terminal_d_040` ID (old format) may have been missed in the rename. |
### Paula (Narrative Depth): APPROVE
Clean migration. New NPC-scoped IDs are a genuine improvement for authoring clarity. No dialogue or monologue text was altered. Cross-character prerequisite references are stable. Flags the same mood vocabulary issues as warnings (items 1-2 above) and notes `opening-hook-content.md` has pre-existing design doc drift.
### Miri (World Consistency): REQUEST_CHANGES
Thorough world consistency check. IP originality and lore are clean. Three substantive issues:
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | PC monologue files (all locations) | **critical** | **Namespace collision** — `pc-detective_m_d_001` exists in `the-terminal.yaml`, `the-last-shift.yaml`, `maintenance-corridors.yaml`, AND `opening.yaml`. Four distinct lines with identical IDs. Engine will silently overwrite or error. Two resolution options: (A) location prefix in ID like `pc-detective_m_d_term_001`, or (B) reserved number ranges per file. |
| 2 | `dialogue/the-last-shift/bar-owner.yaml` `bar-owner_d_018` | warning | Lera Sessik's tenure: says "twelve years" but NPC profile and Sera Venn's two lines all say "eighteen years". |
| 3 | `dialogue/maintenance-corridors/ring-operative.yaml` | warning | `fact_id: location.surveillance_gaps` should be `investigation.surveillance_gaps` per the knowledge vocabulary doc. Mismatched namespace means detective prerequisite gates will never fire from this grant. |
### Verdict: CHANGES REQUESTED
**2 critical issues must be resolved before merge:**
1. **Mood vocabulary** in `line-pool-format.md` §6.5 and style guide §11 — mechanical fix, update to post-Sprint-14 values (`anxious`, `frustrated`, `content`, `suspicious`, `warm`, `hostile`, `relieved`, `focused`)
2. **PC monologue ID collision** — all PC monologue files share `pc-detective_m_d_001` / `pc-smuggler_m_s_001` across locations. Schema design question that needs a decision before the migration is finalized.
**3 warnings worth fixing in the same pass:**
- Lera's tenure (twelve → eighteen)
- `location.surveillance_gaps` → `investigation.surveillance_gaps`
- Orphaned old-format ID in maintenance-tech.yaml
Address review comments from Hoshe, Paula, and Miri:
- Update mood vocabulary in 3 docs (line-pool-format.md §6.5,
style-guide §11, content-directory-structure.md Appendix B) from
pre-Sprint 14 values to current D-035 enum
- Fix worked example IDs in line-pool-format.md §3.5 to match
actual the-last-shift kael-davan sequence (_015, _024, _026)
- Fix Section 5.1 restart note to describe multi-location continuity
- Fix style-guide §16 worked example: dock-worker_d_071 → kael-davan_d_076
- Fix stale mood reference in style-guide §16 Step 3
- Fix orphaned the-terminal_d_040 in maintenance-tech.yaml comment
- Fix orphaned the-terminal_d_008/018 in smuggler-inventory.yaml
- Fix Lera tenure: twelve → eighteen years (bar-owner_d_018)
- Fix fact_id: location.surveillance_gaps → investigation.surveillance_gaps
in ring-operative.yaml (2 occurrences)
- Fix NPC name: Lera Osk → Lera Sessik in bar-owner.yaml comment
- Fix mood line format example in style-guide §5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
NPC-scoped line ID scheme (D-035) works for hand-authored content but
will produce slug collisions with auto-generated populations (D-029).
Tracked as open question with ticket #544.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
the-terminal_d_039) to NPC-scoped (kael-davan_d_001) format per D-035 Sprint 15 amendmentZero content changes — pure ID substitution. The old location-scoped scheme already caused a collision (
the-terminal_d_039in two files) and would not scale to procedurally generated populations (D-029).Pre-PR notes
make pre-pr-validatepasses for all dialogue/monologue content (0 new errors)fact_idreferences in NPC profiles, npc_count mismatch) are pre-existing issues outside this ticket's scopemake pre-pr-lintfails on pre-existing Rust clippy issues inserver/— not introduced by this change (all 45 changed files are content/docs)Test plan
make pre-pr-validateshows no dialogue ID duplicates or schema errors_d_0[0-9][0-9][0-9]in dialogue files confirms NPC-slug prefixes only🤖 Generated with Claude Code
Review: copy -> main (type: copy) — APPROVED with notes
Three reviewers (Hoshe QA, Paula narrative, Miri world consistency) reviewed 46 changed files.
Summary
The mechanical line ID migration is correct: all 20 dialogue files and 14 monologue files use NPC-scoped IDs, no old location-slug format survives, and multi-location NPC sequences are globally unique (kael-davan 001-075 across 3 files, pc-detective and pc-smuggler 001-008 across 2 files each). No dialogue text, tags, or dual_lens entries were changed. Schema descriptions and authoring docs updated.
Notes for follow-up (not blocking merge)
Documentation stale examples (3 warnings):
docs/architecture/line-pool-format.mdSection 3.5: worked example showskael-davan_d_001at the-last-shift (should be_d_015after renumbering)docs/architecture/line-pool-format.mdSection 5.1: "Sequence restarts at _001 per file" note contradicts multi-location implementationcontent/_meta/npc-authoring-style-guide.mdSection 16: worked example uses role-scoped IDdock-worker_d_071while citing NPC-scoped complianceStale mood vocabulary (3 warnings, pre-existing):
docs/architecture/line-pool-format.mdSection 6.5,docs/design/content-directory-structure.mdAppendix B, andcontent/_meta/npc-authoring-style-guide.mdSection 11 all list pre-Sprint 14 mood valuesMonologue ID uniqueness (noted, deferred):
Minor (suggestions):
bar-owner.yamlline 3: comment says "Lera Osk" — canonical is "Lera Sessik"sera-venn.yamlline 17: header cross-reference off by 2 linesContent validation: 0 schema errors, 0 new cross-ref errors (9 pre-existing fact_id errors, 21 pre-existing relationship warnings).
Test Report: PR #59 — Line ID Namespace Migration (D-035 Sprint 15)
docs/architecture/line-pool-format.mdSection 5Verdict: REQUEST_CHANGES
One critical issue, two warnings, three suggestions. The migration is mostly correct — 37 of 40 content files follow the NPC-scoped format without problems. The critical issue is two surviving old-format ID references in unchanged files that reference renamed IDs. The blocking issue is in
docs/architecture/line-pool-format.md, which is a changed file in this PR with a stale mood vocabulary table that is now actively wrong documentation for authors consulting it after merge.Summary
The mechanical ID rename is correctly applied across all 20 dialogue pool files and 14 monologue pool files. All new IDs match the
{npc-slug}_{d|m}_{###}and{npc-slug}_m_{s|d}_{###}patterns. No old location-scoped IDs (the-terminal_d_xxx,the-last-shift_d_xxx) survive in the renamed content files. Multi-location NPC sequences (kael-davan, pc-detective, pc-smuggler) are globally unique and continuous across their location files, which matches the intent stated in the PR description. Schema descriptions are updated. Authoring style guide is updated.Two orphaned old-format references survive in files not included in this PR's diff. Since
line-pool-format.mdis a changed file in this PR, the stale mood vocabulary in Section 6.5 is now actively misleading documentation that this PR is in a position to fix.Failures
CRITICAL:
docs/architecture/line-pool-format.mdSection 6.5 — Stale mood vocabularyFile:
/docs/architecture/line-pool-format.mdSeverity: Critical
Section 6.5 "Moods (D-028 Layer 4)" lists:
These are the pre-Sprint 14 mood values. The Sprint 14 amendment to D-035 renamed the mood vocabulary. The current schemas (
dialogue-pool.schema.json,monologue-pool.schema.json) and all YAML content files use:This is a changed file in PR #59. An author consulting this document post-merge would be given vocabulary that fails schema validation. The correct values are already in the schemas and are confirmed by every mood tag in the YAML files in this PR.
Expected: Section 6.5 lists
anxious,frustrated,content,suspicious,warm,hostile,relieved,focusedwith a note referencing the Sprint 14 amendment.Actual: Section 6.5 lists the pre-Sprint 14 vocabulary.
Reproduction: Open
docs/architecture/line-pool-format.mdSection 6.5 and compare tocontent/_schema/dialogue-pool.schema.jsonmood.items.enum.WARNING: Orphaned old-format ID reference in
maintenance-tech.yamlcommentFile:
content/campaigns/main/systems/krenn/stations/sova/districts/transit/dialogue/the-terminal/maintenance-tech.yaml(line 4)Severity: Warning
The comment at line 4 reads:
The ID
the-terminal_d_040is the old location-scoped format. After this migration, the maintenance-tech NPC's first line ismaintenance-tech_d_001. The comment refers to a line that no longer exists under that ID. This is a stale reference that will cause confusion for authors and reviewers looking up line IDs.Expected: Comment references the new ID (
maintenance-tech_d_001or simply describes the line without citing an ID).Actual: Comment references orphaned
the-terminal_d_040.Note: This file is listed in the PR diff. The comment was not updated during the migration pass.
WARNING: Orphaned old-format ID references in
smuggler-inventory.yaml(not in diff)File:
content/campaigns/main/systems/krenn/stations/sova/districts/transit/items/smuggler-inventory.yaml(lines 50-51)Severity: Warning
Lines 50-51 contain:
Both
the-terminal_d_008andthe-terminal_d_018are old location-scoped IDs. After this migration, Kael's terminal dialogue lines arekael-davan_d_034throughkael-davan_d_075. The referenced lines are nowkael-davan_d_041("Manifest says this one's forty kilos over") and the courier line that was formerlythe-terminal_d_018.Note: This file was not included in the PR diff, so this may be a separate ticket. However, PR #59 creates a broken cross-reference in content that was valid before merge. The migration introduced the breakage; the fix should accompany it or be tracked explicitly.
Suggestions (non-blocking)
SUGGESTION:
docs/architecture/line-pool-format.mdSection 3.5 worked example uses stale IDsFile:
docs/architecture/line-pool-format.md, Section 3.5Severity: Suggestion
The worked example in Section 3.5 shows:
After this migration,
kael-davan_d_001is inmaintenance-corridors/kael-davan.yaml("Package is in the junction locker"). The last-shift greeting is nowkael-davan_d_015. The example still compiles and the ID format is correct — the issue is only that the example ID no longer matches the actual text in the YAML. This confuses authors cross-referencing the docs against content.Similarly, the same section example shows
kael-davan_d_010andkael-davan_d_012with last-shift content, but the actual last-shift file now starts at_d_015.This is a "should fix" rather than a blocker.
SUGGESTION:
docs/architecture/line-pool-format.mdSection 5.3 — "Sequence restarts at _001 per file" noteFile:
docs/architecture/line-pool-format.md, Section 5.3Severity: Suggestion
Section 5.3 states:
This contradicts the actual implementation for multi-location NPCs. Kael Davan's sequences are:
maintenance-corridors/kael-davan.yaml:_d_001through_d_014the-last-shift/kael-davan.yaml:_d_015through_d_033the-terminal/kael-davan.yaml:_d_034through_d_075The sequences do not restart. The PR description explicitly describes this as intentional: "multi-location NPC sequences are globally unique continuous sequences." The spec note should be updated to reflect this: globally unique sequences per NPC, not per file. The current note will cause authors to incorrectly restart sequences at
_001for each location file, creating duplicate IDs within the same NPC namespace.SUGGESTION:
bar-owner.yamlheader comment — NPC name inconsistencyFile:
content/campaigns/main/systems/krenn/stations/sova/districts/transit/dialogue/the-last-shift/bar-owner.yaml, line 3Severity: Suggestion
The file header reads:
D-036 canonical NPC naming and D-034 confirmed name is "Lera Sessik" (referenced in
npc-authoring-style-guide.mdSection 2, Tier 2 canonical list: "Lera Sessik (ANCHOR/OPERATOR)"). The comment uses "Lera Osk" which does not match the canonical name. This is pre-existing but the file is included in this PR's diff.Verification Passes
ID format compliance — PASS
All 20 dialogue files: every
id:field matches^[a-z][a-z0-9-]*_d_[0-9]{3}$. No old{location-slug}_d_{###}patterns found in any lineid:field.ID format compliance (monologue) — PASS
All 14 monologue files: every
id:field matches^[a-z][a-z0-9-]*_m_[sd]_[0-9]{3}$. All detective monologue uses_m_d_, all smuggler monologue uses_m_s_.Within-file uniqueness — PASS
All ID sequences within each individual YAML file are unique. No duplicate IDs within any single file.
Multi-location NPC cross-file continuity — PASS
Verified three NPCs with content across multiple location files:
kael-davan:_d_001–_d_014(maintenance-corridors),_d_015–_d_033(the-last-shift),_d_034–_d_075(the-terminal). Continuous, no gaps or overlaps.pc-detective:_d_001–_d_003(the-last-shift),_d_004–_d_008(the-terminal). Continuous.pc-smuggler:_d_001–_d_003(the-last-shift),_d_004–_d_008(the-terminal). Continuous.Monologue restart-per-file pattern — PASS (by design)
Detective and smuggler monologue files each restart at
_001per file. This is correct per the(file_path, line_id)composite key design inline-pool-format.mdSection 5.3. The apparent collisions (multiple files containingpc-detective_m_d_001) are intentional — the engine indexes by file path + ID, not by ID alone.Zero content changes — PASS
No
text:,access:,trust:,situation:,topic:,mood:,tags:,dual_lens:,notes:, orknowledge_grant:fields were modified. Pure ID substitution confirmed across all files.Schema description updates — PASS
Both
dialogue-pool.schema.jsonandmonologue-pool.schema.jsonupdatedidfield descriptions to reference NPC-scoped format. Regex patterns unchanged (prefix pattern^[a-z][a-z0-9-]*already matched NPC slugs).Cross-references in prerequisite blocks — PASS
All
relationship.targetvalues in monologue prerequisites use entity reference format (npc:kael-davan,npc:sera-venn) — these are not line IDs and were not subject to this migration. No prerequisite references use line IDs. No cross-file prerequisite breakage found.Enum vocabulary in content files — PASS
All
mood:,access:,trust:,situation:,topic:values in all 34 content YAML files match current schema enums. The Sprint 14 mood rename (warmnotfond,contentnotcomfortable, etc.) is consistently applied throughout.Notes
The monologue per-file restart is correct. The composite key design means
pc-detective_m_d_001inthe-terminal.yamlandpc-detective_m_d_001inthe-last-shift.yamlare different lines to the engine. This is not a bug. The note inline-pool-format.mdSection 5.3 stating "IDs are not required to be globally unique — npc-slug + file path provides global uniqueness" confirms this. The confusion arises because the dialogue NPCs (kael-davan, pc-detective, pc-smuggler) use globally-unique continuous sequences, while the monologue PC files restart. Both are valid implementations of the spec; they just use different scoping strategies. The spec note "Sequence restarts at _001 per file" (Section 5.3) describes the monologue approach but is incorrect as a general statement because the dialogue multi-location NPCs do not restart.Scope note: The critical
line-pool-format.mdSection 6.5 mood vocabulary issue must be fixed in this PR or before merge, since this PR touches that file and the stale content becomes the documented standard post-merge. All other items are non-blocking suggestions or notes for follow-up tickets.Review: copy (PR #59) → main — type: copy
PR: feat(content): migrate line IDs to NPC-scoped namespace (D-035)
Hoshe (QA): REQUEST_CHANGES
The ID migration is mechanically sound across all YAML files. However:
docs/architecture/line-pool-format.md§6.5fond,comfortable,worried, etc.) — merging this makes stale vocabulary the documented standard. Authors consulting §6.5 get 8 values, 7 of which fail schema validation.content/_meta/npc-authoring-style-guide.md§11dialogue/the-terminal/maintenance-tech.yamlthe-terminal_d_040ID (old format) may have been missed in the rename.Paula (Narrative Depth): APPROVE
Clean migration. New NPC-scoped IDs are a genuine improvement for authoring clarity. No dialogue or monologue text was altered. Cross-character prerequisite references are stable. Flags the same mood vocabulary issues as warnings (items 1-2 above) and notes
opening-hook-content.mdhas pre-existing design doc drift.Miri (World Consistency): REQUEST_CHANGES
Thorough world consistency check. IP originality and lore are clean. Three substantive issues:
pc-detective_m_d_001exists inthe-terminal.yaml,the-last-shift.yaml,maintenance-corridors.yaml, ANDopening.yaml. Four distinct lines with identical IDs. Engine will silently overwrite or error. Two resolution options: (A) location prefix in ID likepc-detective_m_d_term_001, or (B) reserved number ranges per file.dialogue/the-last-shift/bar-owner.yamlbar-owner_d_018dialogue/maintenance-corridors/ring-operative.yamlfact_id: location.surveillance_gapsshould beinvestigation.surveillance_gapsper the knowledge vocabulary doc. Mismatched namespace means detective prerequisite gates will never fire from this grant.Verdict: CHANGES REQUESTED
2 critical issues must be resolved before merge:
line-pool-format.md§6.5 and style guide §11 — mechanical fix, update to post-Sprint-14 values (anxious,frustrated,content,suspicious,warm,hostile,relieved,focused)pc-detective_m_d_001/pc-smuggler_m_s_001across locations. Schema design question that needs a decision before the migration is finalized.3 warnings worth fixing in the same pass:
location.surveillance_gaps→investigation.surveillance_gapsReview comments addressed
All issues from Hoshe, Paula, and Miri have been fixed in
56ed2c8:the-terminal_d_040in maintenance-tech.yaml commentmaintenance-tech_d_001the-terminal_d_008/_018in smuggler-inventory.yamlkael-davan_d_041/_051location.surveillance_gaps→investigation.surveillance_gapskael-davan_d_076Additional commit
414b8ff: registered Q-028 (collision-resistant line IDs for auto-gen NPCs) in decisions/questions.md with ticket #544.Ready for re-review.
Re-Review: copy (PR #59) → main — type: copy
Hoshe (QA): APPROVE
All 6 previous issues resolved. Mood vocabulary updated, orphaned ID fixed, tenure corrected, fact_id namespace fixed, Q-028 registered.
Paula (Narrative Depth): APPROVE
Fix commits are clean. No narrative content altered. Lera's tenure reads naturally. Q-028 well-framed — recommends Option 4 (composite key).
Miri (World Consistency): APPROVE
Cross-file consistency verified. Tenure matches across bar-owner and sera-venn. fact_id fix correct. Notes
location.surveillance_gapsmissing from vocabulary doc as pre-existing gap.Verdict: APPROVED
Post-merge follow-ups (non-blocking):
location.surveillance_gapsvsinvestigation.surveillance_gapscatalog splitlocation.surveillance_gapsto vocabulary docinvestigation.ring_leadershipmissing from §4.1 table (pre-existing)Pull request closed