Merge remote-tracking branch 'origin/main' into server

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
2026-02-12 18:20:32 +01:00
7 changed files with 517 additions and 305 deletions
+127 -33
View File
@@ -1,18 +1,18 @@
---
name: review-pr
description: >
Review a branch diff with dual agents before merge. Use when the user says
"review-pr", "review this PR", "review this branch", or invokes /review-pr.
Spawns Hoshe (code quality) and Tyre (architecture) in parallel to review
the diff against main. Reports approve/reject with inline comments.
Review a branch diff with team-appropriate agents before merge. Use when the
user says "review-pr", "review this PR", "review this branch", or invokes
/review-pr. Spawns reviewers matched to the branch type (code, copy, visual,
audio) in parallel. Reports approve/reject with inline comments.
user-invocable: true
allowed-tools: Bash, Read, Grep, Glob, Task
---
# PR Review Skill
Dual-agent review of a branch diff against main. Hoshe reviews code quality,
Tyre reviews architecture. Both must approve for a clean review.
Multi-agent review of a branch diff against main. Reviewer composition depends
on the branch type. All reviewers must approve for a clean review.
## Workflow
@@ -32,7 +32,21 @@ Fetch remote branches first:
git fetch --all
```
### 2. Generate the diff
### 2. Determine reviewer team
Map the branch name to a reviewer set. Use the branch prefix (before any `/`
or `-` suffix) to classify:
| Branch type | Branches | Reviewers |
|-------------|----------|-----------|
| **code** | `server`, `client`, `ci`, or unknown | Hoshe (code quality) + Tyre (architecture) |
| **copy** | `copy` | Hoshe (QA) + Paula (narrative depth) + Miri (world consistency) |
| **visual** | `visual` | Hoshe (QA) + Araminta (art direction) |
| **audio** | `audio` | Hoshe (QA) + Ozzie (player experience) |
If the branch name doesn't match any known type, default to **code** reviewers.
### 3. Generate the diff
```bash
git log --oneline main..<branch>
@@ -56,14 +70,17 @@ For large diffs (>1000 lines of source), provide **source files** rather than
raw diff to reviewers — cleaner context, better reviews. Read files with
`git show origin/<branch>:<path>` and include them in the prompt.
### 3. Spawn both reviewers in parallel
### 4. Spawn reviewers in parallel
Use the Task tool to spawn **two agents simultaneously** in a single message.
Use `model: sonnet` for both — sufficient for review, saves cost.
Use the Task tool to spawn **all reviewers simultaneously** in a single message.
Use `model: sonnet` for all — sufficient for review, saves cost.
**Agent 1 — Hoshe (Code Quality)**
- `subagent_type`: `hoshe`
- `model`: `sonnet`
---
#### Code reviews (`server`, `client`, `ci`)
**Hoshe (Code Quality)**
- `subagent_type`: `hoshe`, `model`: `sonnet`
- Prompt: Include source code and commit log. Ask Hoshe to review for:
- Correctness and bug risks
- Error handling gaps
@@ -71,11 +88,9 @@ Use `model: sonnet` for both — sufficient for review, saves cost.
- Code style and clarity
- Security concerns (OWASP top 10, injection risks)
- Performance issues
- Request structured verdict: APPROVE or REQUEST_CHANGES with file-specific comments
**Agent 2 — Tyre (Architecture)**
- `subagent_type`: `tyre`
- `model`: `sonnet`
**Tyre (Architecture)**
- `subagent_type`: `tyre`, `model`: `sonnet`
- Prompt: Include source code and commit log. Tell Tyre to read the relevant
`decisions/*.md` files first, then review for:
- Architectural consistency with project decisions
@@ -84,40 +99,119 @@ Use `model: sonnet` for both — sufficient for review, saves cost.
- Scalability implications
- Whether the change respects non-negotiable baselines (D-010, D-012)
- Tyre can read files directly from the branch using `git show origin/<branch>:<path>`
- Request structured verdict: APPROVE or REQUEST_CHANGES with file-specific comments
### 4. Present results
---
Format the combined review as a table per reviewer:
#### Copy reviews (`copy`)
**Hoshe (QA)**
- `subagent_type`: `hoshe`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Ask Hoshe to review for:
- Formatting consistency (markdown, file naming, frontmatter)
- Broken references or links
- Spelling and grammar
- File organization and structure
- Missing or orphaned files
**Paula (Narrative Depth)**
- `subagent_type`: `paula`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Tell Paula to read the
relevant `decisions/*.md` files first, then review for:
- Narrative quality and character voice consistency
- Whether dialogue and monologue feel authentic to the characters
- Consequences and stakes — do choices carry weight?
- Political and interpersonal depth
- Emotional resonance — does the text make you feel something?
**Miri (World Consistency)**
- `subagent_type`: `miri`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Tell Miri to read the
relevant `decisions/*.md` files first, then review for:
- Lore accuracy — do facts match established setting?
- Internal consistency across files
- IP originality — nothing should read as a copy from another franchise
- Faction, technology, and location details match the worldbuilding docs
- Setting serves gameplay mechanics (asymmetric information, perception)
---
#### Visual reviews (`visual`)
**Hoshe (QA)**
- `subagent_type`: `hoshe`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Ask Hoshe to review for:
- File format and naming conventions
- Asset organization and directory structure
- Missing or broken references in scene/resource files
- Import settings consistency
**Araminta (Art Direction)**
- `subagent_type`: `araminta`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Tell Araminta to read
the style guide and relevant design docs first, then review for:
- Visual consistency with the established style guide
- Color palette adherence
- UI pattern consistency (diegetic-first, clarity over beauty)
- Whether assets scale gracefully (boxes-with-labels to full-art)
- Mood and tone — sleek, advanced, subtle Commonwealth aesthetic
---
#### Audio reviews (`audio`)
**Hoshe (QA)**
- `subagent_type`: `hoshe`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Ask Hoshe to review for:
- File format and naming conventions
- Audio asset organization and directory structure
- Missing or broken references
- Import/bus configuration consistency
**Ozzie (Player Experience)**
- `subagent_type`: `ozzie`, `model`: `sonnet`
- Prompt: Include the changed files and commit log. Ask Ozzie to review for:
- Emotional impact — does the audio enhance the moment?
- Atmosphere and tone — does it feel like the Commonwealth?
- Player feedback clarity — can the player tell what just happened?
- Pacing — do sounds support or fight the gameplay rhythm?
- Memorable moments — will players remember these audio cues?
---
All reviewers: request structured verdict: APPROVE or REQUEST_CHANGES with
file-specific comments.
### 5. Present results
Format the combined review as a table per reviewer. Include one section per
reviewer that was spawned (2 for code/visual/audio, 3 for copy):
```
## Review: <branch> -> main
## Review: <branch> -> main (type: code|copy|visual|audio)
### Hoshe (Code Quality): [APPROVE | REQUEST_CHANGES]
### <Reviewer Name> (<Focus>): [APPROVE | REQUEST_CHANGES]
[Summary]
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | path:line | critical/warning/suggestion | description |
### Tyre (Architecture): [APPROVE | REQUEST_CHANGES]
[Summary]
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | path:line | critical/warning/suggestion | description |
### <Reviewer Name> (<Focus>): [APPROVE | REQUEST_CHANGES]
...
### Verdict: [APPROVED | CHANGES REQUESTED]
```
The overall verdict is APPROVED only if **both** reviewers approve.
The overall verdict is APPROVED only if **all** reviewers approve.
## Prompt template for reviewers
Use this structure when constructing the agent prompts (adapt as needed):
```
Review the following branch diff for merge into main.
Review the following {branch_type} branch diff for merge into main.
Branch: {branch}
Branch type: {branch_type} (code|copy|visual|audio)
Commits:
{commit_log}
@@ -126,7 +220,7 @@ Diff stats:
[Source files or diff here — exclude vendor/generated code]
Review focus: {focus_area}
Your review focus: {focus_area}
Respond with:
1. Verdict: APPROVE or REQUEST_CHANGES
@@ -138,7 +232,7 @@ Respond with:
If no issues found, say APPROVE with a brief positive summary.
```
## Posting results to Gitea
## 6. Posting results to Gitea
After presenting results to the user, post the review as a PR comment:
@@ -149,7 +243,7 @@ tea comment --login schweitz --repo jpmschweitzer/settled-reach <PR_NUMBER> "<re
Use a heredoc for multi-line review bodies:
```bash
tea comment --login schweitz --repo jpmschweitzer/settled-reach <PR_NUMBER> "$(cat <<'REVIEW'
## Dual-Agent Review: <branch> -> main
## Review: <branch> -> main
...review content...
REVIEW
)"
@@ -163,7 +257,7 @@ Note: `tea pr reject` does not work on your own PRs. Use `tea comment` instead.
tea comment --login schweitz --repo jpmschweitzer/settled-reach <PR_NUMBER> "$(cat /tmp/review.md)"
```
## Merging approved PRs
## 7. Merging approved PRs
`tea pr merge` fails (405) when branches have conflicts with main. Merge
locally instead:
+80 -17
View File
@@ -6,7 +6,7 @@ description: >
/start-sprint. Merges main into the team branch, finds the active sprint,
reads the sprint briefing, and presents the work plan with ticket details.
user-invocable: true
allowed-tools: Bash, Read, Grep, Glob
allowed-tools: Bash, Read, Grep, Glob, TeamCreate, Task, TaskCreate, TaskUpdate, TaskList, SendMessage, AskUserQuestion
---
# Start Sprint Skill
@@ -80,25 +80,88 @@ Output a summary:
Do NOT mark any ticket as `in_progress` yet.
### 8. Enter plan mode
### 8. Confirm and spawn the team
After presenting the work plan summary, you MUST enter plan mode using the
`EnterPlanMode` tool. In plan mode:
Before spawning agents, use `AskUserQuestion` to confirm the work plan and
agent lineup with the user. If declined, stop.
1. **Create a concrete sprint plan** — for each actionable ticket, outline:
- What files need to be created or modified
- What the implementation approach is
- What order tickets should be tackled in (respecting dependencies)
- Any open questions or risks per ticket
Once confirmed:
2. **Include blocked tickets** — note what unblocks them and when they might
become actionable during the sprint.
#### 8a. Parse agents from the briefing
3. **Write the plan to the plan file** — the plan should be self-contained so
you can follow it step-by-step once approved.
Extract agent names from the `**Agents:**` line. Format:
```
**Agents:** Name (role), Name (role), ...
```
4. **Exit plan mode** — use `ExitPlanMode` to present the plan for user
approval before starting any implementation work.
Map each name to its `subagent_type` (lowercase):
- "Dudley (simulation)" → `dudley`
- "Stig (UI)" → `stig`
- "Tyre (architecture)" → `tyre`
- "Hoshe (QA)" → `hoshe`
- "Mellanie (author)" → `mellanie`
- etc. (see `.claude/agents/` for full roster)
Only after the user approves the plan should you mark the first ticket as
`in_progress` and begin implementation.
#### 8b. Create the team
```
TeamCreate(team_name: "sprint-{N}-{team}")
```
This makes you the team lead.
#### 8c. Create tasks from tickets
For each ticket in the briefing, create a task:
```
TaskCreate(
subject: "#{id}: {title}",
description: "Full ticket details from step 5, plus briefing notes
and integration points for this ticket.",
activeForm: "Working on #{id}: {short_title}"
)
```
After creating all tasks, mirror the dependency chain from the briefing
using `TaskUpdate` with `addBlockedBy`.
#### 8d. Spawn agents
For each agent from the `**Agents:**` line, spawn a teammate in the
background. Spawn all agents in parallel (one message, multiple Task calls):
```
Task(
subagent_type: "{name_lowercase}",
team_name: "sprint-{N}-{team}",
name: "{name_lowercase}",
prompt: "You are on the {team} team for Sprint {N}.
Branch: `{team}`
1. Read the sprint briefing: docs/sprints/sprint-{N}/{team}.md
2. Read the decision files referenced in the briefing.
3. Check TaskList for available work.
4. Claim an unblocked task (TaskUpdate with owner: your name),
mark it in_progress, and implement it.
5. When done, mark the task completed and check TaskList for
the next available task.
Use `db/connectors/ticket show <id>` for full ticket specs.",
description: "Sprint {N} {team}: {name}",
run_in_background: true
)
```
#### 8e. Report
Output to the user:
- Team name: `sprint-{N}-{team}`
- Agents spawned (names and roles)
- Tasks created (count actionable vs blocked)
- How to interact: `SendMessage` to talk to agents, `TaskList` to
check progress
You are now the team lead. Agents work autonomously — monitor via
`TaskList`, communicate via `SendMessage`, and handle blockers as
they arise.
+3
View File
@@ -14,6 +14,8 @@ Format based on [Keep a Changelog](https://keepachangelog.com/).
- Daily routine system (#88) — NpcPlugin with PreviousDayPhase resource and check_phase_transition system issuing PathRequests at day-phase boundaries
- Multiple NPC spawning (#84) — 3 distinct NPCs (dock worker, field tech, guard) with full component bundles and RelationshipGraph edges
- Observation event generator (#239) — RoutineDeviation, Absence, and NewEntity triggers from comparing visible snapshot against NPC routines and knowledge state
- Review-pr skill routes reviewers by branch type — server/client get Hoshe+Tyre, copy gets Hoshe+Paula+Miri, visual gets Hoshe+Araminta, audio gets Hoshe+Ozzie
- Start-sprint skill spawns team agents from sprint briefings — parses the Agents line, creates a team with tasks from tickets, and launches all listed agents as background teammates
### Fixed
- IPC error handling (#341) — DeserializationWithDump/MutexPoisoned error variants, hex dump logging on deserialization failure, graceful error classification in bridge I/O systems
@@ -22,6 +24,7 @@ Format based on [Keep a Changelog](https://keepachangelog.com/).
- Clippy warnings from Rust 1.93 — derive Default, is_multiple_of, collapsible if
### Changed
- Sprint 3 "Know" team briefings regenerated from database — all four files (server, client, joint, copy) now match actual sprint 3 ticket assignments
- Ticketing database moved to shared worktree location (`../settledreach.db`) — eliminates binary merge conflicts across branches
- All Python connectors use script-relative path resolution instead of `$REPO_ROOT` env var or git rev-parse
- `$REPO_ROOT` environment variable removed — all scripts, skills, and docs use relative paths
+30 -26
View File
@@ -1,16 +1,15 @@
# Sprint 3: Know — Client Tasks
# Sprint 3: Content Foundation — Client Tasks
**Goal:** Player character can observe NPCs, track their knowledge, and interact with the environment through a working observation event pipeline.
**Goal:** Build client-side interaction infrastructure to support v0.1 gameplay.
**Branch:** `client`
**Agents:** Stig (UI), Tyre (architecture), Hoshe (QA)
## Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #345 | Fix entity_renderer.gd field name bug (id vs entity_id) | — |
| #240 | Player interaction system and dispatcher | — |
| # | Title | Priority | Blocked by |
|---|-------|----------|------------|
| #405 | Interaction prompt — client extensible prompt system | high | #404 |
Use `db/connectors/ticket show <id>` for full details.
@@ -22,33 +21,38 @@ Use `db/connectors/ticket show <id>` for full details.
## Notes
**#345 (Critical bug fix):**
- **Context:** Line 26 of `client/scripts/rendering/entity_renderer.gd` checks `entity_data.has("entity_id")` (correct per Protocol v2), but this was identified as a field name bug in the Architecture Review Audit. Verify the check is correct and that entities render properly. If the bug is real, the fix is trivial (XS effort). If entities already render, mark done and document why the audit flagged it incorrectly.
- **File:** `/var/home/jeroenschweitzer/Projects/settled-reach/main/client/scripts/rendering/entity_renderer.gd`
- Start with this — it's blocking basic entity rendering if the bug is real.
**#405 (Interaction prompt system):**
**#240 (Interaction system):**
- **Context:** General-purpose interaction dispatcher that routes player Interact input to appropriate subsystems. Currently there is no interaction system — player can move but not interact with anything.
- **Routing logic:**
- NPC → dialogue (Sprint 4+, stub for now)
- Object → examine (Sprint 4+, stub for now)
- Door → open/close (Sprint 4+, stub for now)
- Terminal → info access (Sprint 4+, stub for now)
- **Implementation:** Add `Interactable` component concept on server side. Client sends `Interact` input when player presses interact key near an entity. Server dispatcher checks entity type and routes to appropriate handler. For Sprint 3: infrastructure only, all handlers return placeholder text.
- **Files:**
- Server: `server/src/simulation/interaction.rs` (new module)
- Client: `client/scripts/autoloads/input_mapper.gd` (add interact key binding)
- **Integration:** Builds on existing input system (`server/src/simulation/input.rs`, `client/scripts/autoloads/input_mapper.gd`). New input type: `PlayerInput::Interact { target_entity: Option<u64> }`.
- This is foundation work for dialogue (#168, Sprint 4+) and follow/examine mechanics (#241, #242, Sprint 4+).
Client-side interaction prompt designed for extensibility from day one. v0.1 implementation: single context-sensitive "E" prompt (pick first available verb). Architecture supports v0.2 multi-verb radial menu (show all available verbs from server).
**Context:** This is a new system — currently the player can move but cannot interact with NPCs, objects, or environment. This ticket adds the UI layer that receives `InteractionOptions` data from the server (via ObserverSnapshot v3, ticket #404) and displays the appropriate prompt.
**v0.1 behavior:**
- Server sends `InteractionOptions { verbs: ["Talk", "Examine"] }` for an NPC in proximity
- Client picks first verb ("Talk") and displays "E - Talk to [NPC Name]"
- Player presses E → client sends interaction request to server
**v0.2 behavior (architecture must support this):**
- Client displays radial menu with all verbs
- Player selects verb → client sends specific verb + target to server
**Separation of concerns:** This is NOT ticket #240 (Player interaction system and dispatcher). #240 was the general-purpose dispatcher infrastructure. This ticket (#405) is specifically the UI prompt system that reads `InteractionOptions` from server state and displays context-sensitive interaction prompts. Different team, different scope, different definition of done.
**Files:**
- `client/scripts/ui/interaction_prompt.gd` (new UI component)
- `client/scripts/protocol/local_bridge.gd` (read InteractionOptions from ObserverSnapshot v3)
**Blocked by #404:** Cannot implement until server sends `InteractionOptions` data via ObserverSnapshot v3 protocol extension.
**Integration:** Reads from existing IPC bridge. Display layer only — no game logic. All interaction logic stays on server side (ticket #404).
## Dependency Chain
```
#345 (bug fix) → standalone, critical for entity rendering
#240 (interaction dispatcher) → #168, #241, #242 (Sprint 4+ dialogue/mechanics)
#404 (server: proximity + InteractionOptions) → #405 (client: interaction prompt)
```
Both tickets are independent and can run in parallel if multiple agents are available.
Single ticket this sprint. Start as soon as #404 (server) is complete.
## PR Workflow
+170 -141
View File
@@ -1,154 +1,183 @@
# Sprint 3: Know — Copy Tasks
# Sprint 3: Content Foundation — Copy Tasks
**Goal:** Complete the knowledge vocabulary document to unblock content authoring.
**Goal:** Build the content design foundation for v0.1 — character specs, patterns, content structure, and wiki maintenance.
**Branch:** Content work feeds into multiple branches (no code branch)
**Agents:** Mellanie (authoring), Paula (narrative design), Gestalt (systems design)
**Branch:** Content work feeds into multiple branches (no dedicated code branch)
**Agents:** Mellanie (authoring), Paula (narrative design), Gestalt (systems design), Miri (world-building)
## Carry-over from Sprint 2
## High Priority Tickets
| # | Title | Status | Notes |
|---|-------|--------|-------|
| #368 | Knowledge vocabulary for v0.1 content | in_progress | Started Sprint 2, carries to Sprint 3 |
| # | Title | Blocked by |
|---|-------|------------|
| #374 | Update entity-attributes.md — smuggler role-perspective keys | — |
| #377 | Fix Triangle 1 (Hub Power) — Volume Escalation decision | #376 |
| #380 | THE MIRROR pattern spec | — |
| #381 | PC-as-NPC unified spec | #374 |
| #382 | Smuggler voice card + moral arc spec | #374, #261 |
| #384 | Content directory structure design doc | — |
| #396 | Apply Round 2 NPC pattern/motivation mapping | — |
| #400 | v0.1 wow moment content checklist | — |
## Context
## Medium Priority Tickets
Sprint 2 started the knowledge vocabulary document (`docs/design/knowledge-vocabulary-v0.1.md`). Sprint 3 completes it.
| # | Title | Blocked by |
|---|-------|------------|
| #371 | Apply canonical full names to all NPC wiki pages | — |
| #372 | Rename Hael → Naia Tamm across all wiki files | — |
| #375 | Standardize location shortcodes in monologue-guide.md | — |
| #376 | Stub NPC profile for Nils Davan (off-stage) | — |
| #397 | Drin Tier 2 profile expansion | #396 |
| #402 | v0.1 interaction verb spec + verbs[] terminology | — |
The knowledge graph data structures are implemented (Sprint 2, tickets #361-367). The observation event pipeline is being built (Sprint 3, ticket #239). The content team needs to define what *goes into* those containers — the FactIds, EntityKnowledge attribute keys, and RelationshipState transition triggers that actual gameplay content will reference.
Without this vocabulary:
- Mellanie can't write monologue prerequisites (`prerequisite: { suspects: "manifest_discrepancy" }` — is `manifest_discrepancy` a valid FactId?)
- Paula can't design NPC profiles with knowledge gates (what `known_attributes` keys exist?)
- The observation event generator (#239) can't map NPC behaviors to meaningful triggers (what counts as a "social anomaly"?)
This ticket unblocks content authoring ticket #309 (Sprint 4+) and is the bridge between knowledge graph implementation and actual content.
## Assigned Ticket
| # | Title | Priority | Est. | Blocked by |
|---|-------|----------|------|------------|
| #368 | Knowledge vocabulary for v0.1 content (#309) | high | 0.5d | — |
Use `db/connectors/ticket show 368` for full details.
## What You're Delivering
A design document: `docs/design/knowledge-vocabulary-v0.1.md`
The document must define:
### 1. FactId Categories for v0.1
`FactId` is the identifier for non-entity knowledge (see `server/src/knowledge/types.rs` lines 21-25). Format: `"category.topic"` (e.g., `"contraband.ring_exists"`).
Define 15-25 concrete FactIds for v0.1 scope covering:
- **Contraband knowledge** (ring existence, lattice components, medical-grade replacements, Severance tech per D-037)
- **Location knowledge** (restricted corridors, smuggling routes, surveillance coverage, span gate schedules)
- **Event knowledge** (manifest discrepancies, suspicious meetings, evidence discoveries)
- **World knowledge** (Commission regulations, Syndic supply chains, Sova District context per D-036)
- **Relationship knowledge** (trust networks, faction allegiances, personal connections)
- **Investigation progress** (investigation stages, evidence collected, confrontation triggers)
Each FactId must map to the 4-level confidence hierarchy (Suspects / KnowsOf / KnowsDetails / Direct). Example:
```
contraband.ring_exists
- Suspects: "There's off-the-books cargo moving through here"
- KnowsOf: "There's a smuggling ring operating in Sova"
- KnowsDetails: "Kael, Voss, and Drin are running lattice components through customs bypass"
location.corridor_b7_restricted
- Suspects: "B-7 access is tighter than it should be"
- KnowsOf: "B-7 requires dock credentials after 18:00"
- KnowsDetails: "B-7 is the primary smuggling handoff point, Commission sweeps at shift change"
```
### 2. EntityKnowledge Attribute Keys
`EntityKnowledge.known_attributes` is a `BTreeMap<String, String>` (see `server/src/knowledge/types.rs` lines 163-165). Define the canonical keys for v0.1:
- **Identity:** `name`, `role`, `faction`, `species` (human assumed for v0.1)
- **Social:** `relationship_type` (colleague, friend, regular, contact, rival), `trust_level` (low/medium/high)
- **Behavioral:** `routine_pattern` (shift worker, bar regular, transient), `behavior_flags` (avoidant, talkative, nervous, defensive)
- **Secrets:** `secret_held` (freeform description), `secret_confidence` (Suspects/KnowsOf/KnowsDetails)
- **Investigation:** `tell_observed` (description of observable tell), `contradiction_flagged` (yes/no)
Provide 3-5 example EntityKnowledge entries for v0.1 NPCs (Kael Davan, Sera Venn, Lera Sessik, Torek Lintar, Voss Krenn) showing how these keys populate. Use D-034 FRIEND profiles as reference.
### 3. RelationshipState Transition Patterns
`RelationshipState` drives entity color rendering (see D-033, `server/src/knowledge/types.rs` lines 117-140). The enum is:
- `Unknown` (teal)
- `Known` (soft green)
- `Friendly` (soft green, trusted)
- `PersonOfInterest` (amber, flagged by investigation)
- `Hostile` (red, character knows there is danger)
Define the canonical transition triggers for v0.1:
**Unknown → Known:**
- First direct observation with name attribution
- Told about entity by trusted source
**Known → Friendly:**
- Trust-gated dialogue completed (D-028 Layer 3 "real" tier accessed)
- Multiple positive interactions without contradictions
- Entity provides useful information
**Known/Friendly → PersonOfInterest:**
- Monologue triggers "something's off" (Suspects-level knowledge about this entity's contradiction)
- Observable tell detected (D-034 tell system)
- Entity avoids specific topics or NPCs
**PersonOfInterest → Hostile:**
- KnowsDetails-level knowledge of entity's threat to player
- Direct observation of hostile action
- Contradiction confirmed (THE FRIEND arc climax, D-034)
**Known/Friendly → Hostile:**
- Direct observation of hostile action with no warning
- Emergency trust collapse (rare)
### 4. Observation Event Trigger Definitions
The observation event generator (#239) needs to know what counts as a "meaningful observation." Define the 5 trigger types with concrete examples:
1. **Routine deviation:** NPC not at expected location during their scheduled time
2. **Absence detection:** Expected NPC missing from usual location
3. **Social anomaly:** Unexpected NPC pairing or avoidance behavior
4. **New information:** First observation of an entity/location/behavior
5. **Contradiction:** Observed behavior conflicts with told information
Each trigger type should map to specific NPC axis data (D-024) and monologue tone.
Use `db/connectors/ticket show <id>` for full details.
## Key Decisions
- `decisions/architecture.md` — D-041 (Knowledge Graph Data Model — canonical structs)
- `decisions/content.md` — D-024 (10-axis NPC model), D-034 (THE FRIEND pattern), D-035 (tag taxonomy), D-036 (Sova setting), D-037 (contraband)
- `decisions/perception.md` — D-016 (internal monologue), D-033 (entity color = relationship)
## Canonical References
- Knowledge graph structs: `server/src/knowledge/types.rs`
- Knowledge graph canonical design: `docs/workshops/knowledge-graph-information-boundaries/round2-synthesis.md` (Part 3, lines 320-752)
- THE FRIEND profiles: D-034 (Kael Davan, Sera Venn)
- Setting details: D-036 (Sova Transit District, Krenn System)
- Contraband details: D-037 (lattice components)
## Completion Criteria
The document is complete when:
1. All 4 sections (FactIds, EntityKnowledge keys, RelationshipState triggers, Observation triggers) are filled with concrete examples
2. Each FactId has confidence-level descriptions
3. EntityKnowledge examples cover at least 3 v0.1 NPCs
4. RelationshipState transitions map to specific gameplay events
5. Observation triggers reference specific NPC axis combinations
This unblocks #309 (content authoring), which is the first monologue/dialogue writing ticket.
- `decisions/content.md` — D-024 (10-axis NPC model), D-034 (THE FRIEND pattern), D-035 (dialogue tag taxonomy), D-036 (Sova setting), D-037 (contraband)
- `decisions/perception.md` — D-016 (internal monologue), D-033 (entity color)
- `decisions/scope.md` — D-027 (vertical slice criteria)
## Notes
- **Sprint 2 progress:** If significant work was done in Sprint 2, review and complete remaining sections. If minimal progress, prioritize FactIds and EntityKnowledge keys first (those block #309 most directly).
- **Cross-team coordination:** Observation event trigger definitions should align with server ticket #239 implementation. Gestalt should coordinate with Dudley on trigger semantics.
- **Authoring ergonomics:** The vocabulary should be *author-friendly*. FactIds should read like natural language. Attribute keys should be memorable. Avoid cryptic codes.
### Critical Path: Content Infrastructure
**#384 (Content directory structure design doc) → blocks server tickets #385, #386:**
Document the converged content directory structure from workshop outputs. This is a **blocker for all server content implementation work**. Required elements:
- Canonical layout: `_meta/`, `_schema/` (infrastructure, underscore prefix), `global/` (factions, technology, contraband, knowledge, enums, regions), `districts/sova-transit/` (district.yaml, npcs/, locations/, templates/, triangles/, lines/)
- `canonical_id` format: `{system}.{station}.{district}.{type}.{slug}` (e.g., `krenn.sova.transit.npc.kael-davan`)
- Mod-compatible directory conventions (no overlay implementation needed for v0.1, just structure)
- District as atomic pack unit
**Files:** `docs/design/content-directory-structure.md` (new)
This ticket is HIGH PRIORITY and blocks server work. Complete early in sprint.
### Character Foundation
**#374 (Entity attributes update) → blocks #381, #382:**
Add 4 new role-perspective keys to entity-attributes.md: `risk_assessment`, `loyalty_assessment`, `position_integrity`, `moral_weight`. Rename `secret_held``leverage_held` (broader scope: secrets, debts, promises, obligations). Rename `secret_confidence``leverage_confidence`. Update `trust_level` description to absorb trust_read scope. All keys are observer→target relationships. Total after update: 16 canonical keys.
**Files:** `docs/wiki/entity-attributes.md`
**#380 (THE MIRROR pattern spec):**
Define the honest-character NPC pattern. No contradiction arc, no secret, no tell. Tier 1 emotional depth. Pattern definition with mechanical rules, content requirements (50-70 lines, 10-axis profile), tell system rules (MIRROR has none). Naia Tamm as reference implementation. Output becomes generator template.
**Files:** `docs/design/npc-patterns/the-mirror.md` (new)
**#381 (PC-as-NPC unified spec):**
Unified spec for treating player characters as NPCs when not controlled. Required elements: starting knowledge graph, starting relationship map, reverse knowledge (bidirectional — critical for Gestalt's swappable PC vision), orientation monologue (Ozzie first 60 seconds), agency boundaries, authored relationship stubs (Gore requirement), tell inversion. 9-step conversion checklist for content authors. v0.1 scope: 2 PC briefs (smuggler, detective).
**Files:** `docs/design/pc-as-npc-spec.md` (new)
**#382 (Smuggler voice + moral arc):**
Two deliverables:
1. **Voice card:** Paired examples with detective showing dual-lens register differences. Thinks in people vs data, first names vs surnames, fragments vs complete sentences, Krenn substrate vocabulary.
2. **Moral arc:** 4 phases (Comfort, Doubt, Reckoning, Compromise), smuggler-specific FactIds, monologue triggers.
Subsumes #310 (Character voice speech patterns).
**Files:** `docs/design/smuggler-voice-card.md`, `docs/design/smuggler-moral-arc.md` (new)
### Triangles and NPC Content
**#377 (Triangle 1 Volume Escalation decision):**
Add smuggler decision fork to Triangle 1 (Hub Power): side with Nils (louder signal), side with Voss (internal tension), or split the route (new exposure surface). Each option cascades within T1 only — self-contained, no cross-triangle cascade (A-17). Includes Nils partial presence via lattice message (~5-8 lines).
**Blocked by #376** (Nils Davan stub profile — currently referenced in 5+ NPC profiles but has no wiki page).
**Files:** `docs/wiki/triangles/triangle-1-hub-power.md`
**#396 (Apply Round 2 NPC pattern/motivation mapping):**
Apply the Round 2 finalized NPC pattern/motivation mapping (Gestalt-Paula synthesis from workshop) to wiki and content files. 17 NPCs × (pattern + motivation). Includes Harek structural role formalization (Paula Gap 7 resolution).
**Files:** All NPC wiki pages in `docs/wiki/npcs/`
**#397 (Drin Tier 2 expansion):**
Drin confirmed promoted to Tier 2 (A-01 consensus). Expand wiki profile to full Tier 2 depth: all 10 profile axes, smuggler lens section, triangle membership formalized for T2 and T5.
**Blocked by #396** (pattern/motivation must be applied first).
**Files:** `docs/wiki/npcs/drin-rosta.md`
### Specifications and Documentation
**#400 (v0.1 wow moment content checklist):**
Map D-039 6 wow moments to specific content deliverables + implementation tickets. Track completion. Acceptance: every moment has identified content + code backing it.
**Files:** `docs/design/v0.1-wow-moments-checklist.md` (new)
**#402 (Interaction verb spec):**
Document the 7 interaction types from workshop (A-04): Move, Look, Monologue, Examine Object, Examine NPC, Talk, Overhear. Define triggers, UI needs, server events per type. v0.1 surfaces single context-sensitive action; architecture supports N verbs via `verbs[]`. Includes wiki + decisions rename to `verbs[]` terminology where appropriate. Soft dependency for ticket #404 (server InteractionOptions).
**Files:** `docs/design/interaction-verbs-v0.1.md` (new)
### Wiki Maintenance (Medium Priority)
**#371 (Canonical full names):**
Apply Miri's 12 full names to NPC wiki pages. Update Core Identity blocks, environmental text references (manifests, shift rosters, Commission kiosk). Names: Voss→Arvo Voss, Devra→Devra Talsen, Resha→Resha Neven, Harek→Harek Valde, Renn→Renn Harsk, Pell→Pell Torssen, Drin→Drin Rosta, Sess→Sess Kolvur, Olin→Olin Tavren, Sabel→Sabel Hersk, Tav→Tav Merik.
**Files:** All NPC wiki pages, environmental description documents
**#372 (Hael → Naia Tamm rename):**
Phonetic collision fix (Kael/Hael). Find-and-replace across ~16 files (Paula full cascade). Triangle 4 becomes Naia-Kael-Sera. Update all relationship references, triangle diagrams, cross-references.
**Files:** All files referencing Hael (wiki, triangles, design docs)
**#375 (Location shortcode standardization):**
Fix hub_m_ → terminal_m_ inconsistency in monologue-guide.md. Canonical shortcodes: terminal, bar, corridor. Add shortcode reference table. Add situation overlap rules and mood exclusivity rules.
**Files:** `docs/design/monologue-guide.md`
**#376 (Nils Davan stub profile):**
Minimal off-stage profile: Core Identity, relationship to Kael (siblings), role in ring (upstream pressure), known attributes by other NPCs. Referenced in 5+ NPC profiles but has no wiki page.
**Files:** `docs/wiki/npcs/nils-davan.md` (new, stub)
## Dependency Chain
```
High-priority critical path:
#384 (content structure doc) → server #385 (directory skeleton) → server #386 (schemas)
Character foundation:
#374 (entity attributes) → #381 (PC-as-NPC spec)
→ #382 (smuggler voice/arc)
Triangle content:
#376 (Nils stub) → #377 (Triangle 1 decision fork)
NPC content:
#396 (pattern/motivation mapping) → #397 (Drin Tier 2 expansion)
Parallel work (no blockers):
#380 (MIRROR pattern), #400 (wow moments checklist), #402 (verb spec)
#371 (full names), #372 (Hael rename), #375 (location shortcodes)
```
**Start immediately:** #384 (blocks server work), #374 (blocks character specs), #380, #396, #400, #402, #371, #372, #375, #376.
## Sprint Completion Proof
Copy work is complete when:
1. Server team can start building content/ directory (#385) — requires #384
2. Character voice/patterns are specified — #380, #381, #382 complete
3. All 17 NPCs have pattern/motivation assigned — #396 complete
4. Triangle 1 has decision fork content — #377 complete
5. Wiki maintenance is current — full names, Hael→Naia rename, location shortcodes standardized
6. v0.1 wow moments are mapped to deliverables — #400 complete
This sprint establishes the content design layer that all v0.1 authoring depends on.
+68 -58
View File
@@ -1,87 +1,97 @@
# Sprint 3: Know — Joint Tasks
# Sprint 3: Content Foundation — Joint Tasks
**Goal:** Player character can observe NPCs, track their knowledge, and interact with the environment through a working observation event pipeline.
**Goal:** Coordinate cross-team dependencies for content infrastructure and interaction systems.
**Branches:** `server` + `client` (merge to main for integration)
**Branches:** Work happens on separate branches, coordinates through main.
## Joint Tickets (Split Per Team)
## Cross-Team Dependencies
Joint tickets are split between server and client teams. Work happens on separate branches, merges through main.
Sprint 3 has a tight dependency chain between copy and server teams:
### #341: Basic IPC error handling implementation
```
Copy team:
#384 (content directory structure doc)
Server team:
#385 (create content/ directory skeleton)
#386 (content schema definitions)
#392 (make validate-content CLI)
**Split:**
- **Server half:** Deserialization failure handling (log + dump raw bytes), clean shutdown on pipe break
- Assigned to: server team (Dudley)
- Files: `server/src/bridge/local.rs`, `server/src/bridge/tcp.rs`
- **Client half:** Server crash detection (SIGCHLD), error dialog with last log lines, pipe break handling
- Assigned to: client team (Stig)
- Files: `client/scripts/protocol/server_process.gd`, `client/scripts/protocol/local_bridge.gd`
Server team:
#404 (proximity detection + InteractionOptions)
Client team:
#405 (interaction prompt system)
```
**Blocker:** None — both sides can implement independently against the D-020 IPC contract.
## Critical Path Management
### #84: Multiple entity sync
**#384#385#386#392 pipeline:**
**Split:**
- **Server half:** Add 2-3 NPCs to simulation with proper TilePosition + Npc components, ensure all appear in ObserverSnapshot
- Assigned to: server team (Dudley)
- Files: `server/src/main.rs` (world spawn setup)
- Depends on: #86 (NPC components), #236 (done)
- **Client half:** Verify all entities render correctly from snapshot data, test entity lifecycle (appear/disappear/move)
- Assigned to: client team (Stig)
- Files: `client/scripts/rendering/entity_renderer.gd`
- Depends on: #345 (bug fix)
This is the critical path for all v0.1 content work. The copy team's content structure design doc (#384) must complete before server can build the directory skeleton (#385) or write schema files (#386). All content authoring is blocked until this pipeline completes.
**Integration point:** Both halves can be tested independently (server logs snapshot content, client uses test data), then integrated through the existing IPC bridge.
**Coordination points:**
- Copy team: prioritize #384 early in sprint
- Server team: ready to start #385 immediately when #384 is complete
- Server team: #386 can start in parallel with #385 (both depend on #384)
- Server team: #392 depends on #386 completing
Use `db/connectors/ticket show <id>` for full details.
**#404#405 handoff:**
Server team builds proximity detection + `InteractionOptions` component with `verbs[]` array. Client team builds interaction prompt UI that reads from ObserverSnapshot v3. Server work must complete first.
**Coordination points:**
- Server team: #404 includes ObserverSnapshot v2 → v3 protocol extension
- Client team: cannot start #405 until server publishes v3 protocol changes
- Copy team: #402 (verb spec) is soft dependency — provides verb taxonomy for #404
## Key Decisions
- `decisions/architecture.md` — D-020 (subprocess IPC), D-010 (client-server separation), D-030 (testability)
- `decisions/content.md` — D-024 (NPC model), D-027 (vertical slice criteria)
- `decisions/architecture.md` — D-020 (IPC protocol), D-010 (client-server separation), D-030 (testability)
- `decisions/content.md` — D-024 (NPC model), D-035 (tag taxonomy)
- Content scoping: v0.1 Content Scoping Workshop outputs (parent epic #369)
## Sprint Completion Proof
**"Walk around and notice NPCs"** — the sprint is done when:
Sprint 3 is complete when:
1. Fog and LOS work (Sprint 2 baseline, maintained)
2. Multiple NPCs appear on screen with distinct colors
3. NPCs have daily routines and pathfinding works
4. Player can attempt to interact (dispatcher exists, even if handlers are stubs)
5. Observation events generate when NPCs do something interesting
6. IPC errors display useful messages instead of silent crashes
7. Entity rendering bug (#345) is verified fixed or documented as non-issue
1. **Content infrastructure exists:**
- `content/` directory structure is documented and created
- YAML schemas define content contracts
- `make validate-content` CLI validates content files
**Observation pipeline proof:** Spawn an NPC at a scheduled location. The server generates an observation event when the NPC is in LOS. Logs confirm the event was generated with correct trigger type and NPC reference.
2. **Interaction mechanics work:**
- Server detects proximity and sends `InteractionOptions` to client
- Client displays context-sensitive interaction prompt
- Player can press E to trigger interaction (even if handlers are stubs)
This is the first moment NPCs feel like *people* instead of sprites — they move with purpose, and the game notices when something is off.
3. **Cross-team handoffs succeeded:**
- Copy team delivered #384 on time for server dependencies
- Server team delivered ObserverSnapshot v3 for client integration
- No team was blocked waiting for another team's output
This sprint establishes the content production pipeline and basic player interaction — foundation for all v0.1 gameplay.
## Notes
- **#341 (IPC error handling):** Sprint 1-2 had minimal error handling — crashes were silent or cryptic. This ticket adds the minimum viable error UX: deserialization failures show raw data for debugging, server crashes show log tail in a dialog, pipe breaks shut down cleanly. Improves developer experience and prevents "what just happened" moments.
- **#84 (Multiple entity sync):** Sprint 1-2 had a single player entity. This ticket proves the sync layer works with multiple entities. The server-side work overlaps with #86 (NPC components) — if #86 is done first, this becomes trivial. The client-side work depends on #345 being resolved.
- **Test plan per D-030 Phase 1:** Sprint 3 bridges Phase 1 and Phase 2. Collision/pathfinding tests (#237) continue Phase 1 focus. Observation event generation (#239) is the first Phase 2 work (monologue pipeline integration test).
**Content pipeline coordination:**
## Dependency Chain
The #384#385#386#392 pipeline is sequential work across two teams. To minimize idle time:
- Copy team should communicate #384 progress to server team daily
- Server team can prepare #385 and #386 implementation plans while #384 is in progress
- Server team can start #392 design (CLI interface, validation rules) while #386 is being written
```
Server branch:
#341 (IPC error, server) → standalone, no blockers
#84 (multi-entity, server) → blocked by #86 (NPC components)
**Interaction system coordination:**
Client branch:
#341 (IPC error, client) → standalone, no blockers
#84 (multi-entity, client) → blocked by #345 (bug fix)
The #404#405 handoff is cleaner — less interdependency once the protocol extension is defined. Server team should publish the ObserverSnapshot v3 schema early (even before implementation is complete) so client team can prepare UI layer.
Integration:
Both halves of #341 merge independently
Both halves of #84 merge when both are complete
```
**Parallel work:**
## PR Workflow
While critical path tickets are in progress, both teams have parallel work:
- Copy team: character specs (#380, #381, #382), wiki maintenance (#371, #372, #375, #376), pattern mapping (#396)
- Server team: pause system (#406, independent of all other work)
- Client team: only one ticket this sprint (#405), blocked by server #404
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(scope): description" --description "body" --base main --head <branch>
```
The copy team has the most parallel work available — 14 tickets total, only 3 are blocked at sprint start.
+39 -30
View File
@@ -1,56 +1,65 @@
# Sprint 3: Know — Server Tasks
# Sprint 3: Content Foundation — Server Tasks
**Goal:** Player character can observe NPCs, track their knowledge, and interact with the environment through a working observation event pipeline.
**Goal:** Build the content infrastructure for v0.1 — directory structure, schema validation, and interaction mechanics.
**Branch:** `server`
**Agents:** Dudley (simulation), Tyre (architecture), Hoshe (QA)
## Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #86 | Core NPC components | — |
| #87 | Relationship system | — |
| #88 | Daily routine system | #25 (done) |
| #237 | Tile-based A* pathfinding | #236 (done) |
| #238 | NPC path following and movement | #237 |
| #239 | Observation event generator | — |
| # | Title | Priority | Blocked by |
|---|-------|----------|------------|
| #385 | Create content/ directory skeleton | high | #384 |
| #386 | Content schema definitions (YAML Schema files) | high | #384 |
| #392 | Implement make validate-content CLI | high | #386 |
| #404 | Proximity detection + multi-verb InteractionOptions (verbs[]) | high | — |
| #406 | Pause system — server tick rate scaling | medium | — |
Use `db/connectors/ticket show <id>` for full details.
## Key Decisions
- `decisions/content.md` — D-024 (10-axis NPC model), D-034 (THE FRIEND pattern), D-035 (dialogue tag taxonomy)
- `decisions/architecture.md` — D-041 (Knowledge Graph), D-026 (simulation tiers), D-030 (testability), D-031 (time system)
- `decisions/perception.md` — D-011 (fog/perception), D-016 (internal monologue), D-017 (perception modes)
- `decisions/architecture.md` — D-020 (IPC protocol), D-026 (simulation tiers), D-030 (testability)
- `decisions/content.md` — D-024 (10-axis NPC model), D-035 (dialogue tag taxonomy)
- Content scoping: v0.1 Content Scoping Workshop outputs (parent epic #369)
## Notes
**NPC foundation tickets (#86, #87, #88):**
- **#86 (Core NPC components):** The `Npc` marker component and basic axes already exist in `server/src/npc/mod.rs` (Want, Secret, Relationships, ToleranceThreshold, DailyRoutine, InformationInventory, Contentment, plus supporting axes). This ticket extends those component definitions to match the full D-024 10-axis model with proper field types. DailyRoutine needs to become a structured schedule with time-based location transitions.
- **#87 (Relationship system):** The `Relationships` component exists as a stub. Implement the RelationshipGraph resource (per D-024) for NPC-to-NPC connections with trust/history metadata. Keep per-NPC relationship slots (3 key relationships) for Active-tier NPCs. This is separate from the KnowledgeGraph (what entities *know*) — this is what entities *feel*.
- **#88 (Daily routine system):** Build on SimulationTime (done in #25, `server/src/simulation/time.rs`). DailyRoutine component stores location schedule with day-phase transitions (Morning/Afternoon/Evening/Night per D-031). NPCs transition between locations at phase boundaries. Foundation for routine deviation detection (#243, Sprint 4+).
**Content infrastructure (#385, #386, #392):**
**Pathfinding tickets (#237, #238):**
- **#237 (Pathfinding):** A* pathfinding over the WalkabilityMap (done in #236, `server/src/simulation/movement.rs`). Use the `pathfinding` crate. NPCs request paths between positions; system returns tile sequences. Output: `PathRequest` event + `ComputedPath` component. This blocks routine execution — NPCs can't move between routine locations without pathfinding.
- **#238 (Path following):** Per-tick NPC position updates along computed paths. Separate from pathfinding computation. Smooth interpolation between tiles (fractional TilePosition or separate VisualPosition component). Movement speed parameter. This is the execution system that makes NPCs actually walk.
These three tickets form a pipeline: directory structure → schema definitions → validation tooling.
**Observation pipeline (#239):**
- **#239 (Observation event generator):** The mechanical heart of the game per Gestalt. Compares ObserverSnapshot against character KnowledgeGraph to generate ObservationEvents. Trigger types: routine deviation, absence detection, social anomaly, new information, contradiction. Character-specific — same NPC behavior generates different events for smuggler vs detective. Foundation for monologue generation (#119, Sprint 4+).
- Existing foundation: `server/src/perception/observation.rs` already emits DirectObservation and LeftLOS events. This ticket adds the *interpretation* layer — detecting *meaningful* observations like routine deviations, not just visibility changes.
- Integration points: Reads KnowledgeGraph (Sprint 2, done), reads DailyRoutine (this sprint, #88), emits to a new ObservationEventQueue resource.
- **#385 (Directory skeleton):** Create the converged `content/` directory structure from workshop outputs. Canonical layout: `_meta/`, `_schema/` (infrastructure, underscore prefix), `global/` (factions, technology, contraband, knowledge, enums, regions), `districts/sova-transit/` (district.yaml, npcs/, locations/, templates/, triangles/, lines/). Empty YAML stubs for all major files. This establishes the physical structure that all content authoring depends on. **Blocked by #384** (design doc, copy team).
- **#386 (Schema files):** Write YAML Schema validation files in `_schema/`: npc.schema.yaml (with tier-conditional rules — Tier 1 vs Tier 2 NPC requirements differ), location.schema.yaml, faction.schema.yaml, template.schema.yaml, fact.schema.yaml, dialogue.schema.yaml, monologue.schema.yaml, district.schema.yaml, pool.schema.yaml. These define the contract for all content files. **Blocked by #384** (design doc).
- **#392 (Validation CLI):** Implement `make validate-content` CLI tool. Reads `_schema/` definitions, validates all YAML in `content/`. v0.1 scope: structural validation (required fields, type checks, enum matching) + tier-conditional rules (Tier 1 NPCs need 50-70 lines, Tier 2 need 10-axis profiles). v0.2 scope (future): cross-reference validation (FactId existence checks, NPC slug resolution). This is the same crate as C3 schemas. **Blocked by #386** (schemas must exist first).
These tickets lay the foundation for all content work. Without them, content authors write into the void with no validation feedback.
**Interaction mechanics (#404):**
- **#404 (Proximity + InteractionOptions):** Two deliverables: (1) proximity detection system (determines when player is close enough to interact with an entity), (2) server-side `InteractionOptions` component modeling N available actions per entity via `verbs[]` array. Without proximity, `InteractionOptions` has no trigger. v0.1 client behavior: pick first/best verb automatically. v0.2 client behavior: show context menu with all available verbs. **Architecture requirement:** This must not be throwaway work — the system must support the v0.2 multi-verb menu natively from day one. Includes ObserverSnapshot v2 → v3 protocol extension to send interaction data to client. See ticket #402 (copy team) for verb taxonomy (Move, Look, Monologue, Examine Object, Examine NPC, Talk, Overhear). **Blocks #405** (client interaction prompt, client team).
- **Files:** `server/src/simulation/interaction.rs` (new module), `server/src/bridge/types.rs` (ObserverSnapshot v3 extension)
- **Integration:** Works with existing proximity/spatial queries. The observation system already tracks entity visibility — this extends it to track interaction range (closer threshold than LOS).
**Pause system (#406):**
- **#406 (Tick rate scaling):** Three tick rate states: (1) full speed (normal gameplay), (2) 50% speed (UI overlay open — knowledge panel, dialogue tree — player is reading), (3) 0% (spacebar pause). Server receives pause/speed commands from client via IPC. Medium priority — nice-to-have for v0.1 but not critical path. Improves player experience when reading dialogue or checking knowledge graph.
- **Files:** `server/src/simulation/time.rs` (extend existing SimulationTime with speed scaling)
## Dependency Chain
```
#86 (NPC components) → #239 (needs NPC profiles to compare against)
#87 (relationships) → standalone, feeds NPC generation pipeline (#92, Sprint 4+)
#88 (routines) → #239 (routine deviation requires routine data)
#237 (pathfinding) → #238 (path following) → #101 (routine execution, Sprint 4+)
#239 (observation) → #119 (monologue generation, Sprint 4+)
#384 (design doc, copy) → #385 (directory skeleton) → content authoring
→ #386 (schemas) → #392 (validation CLI) → content authoring
#404 (proximity + verbs[]) → #405 (interaction prompt, client)
#406 (pause) → standalone
```
#86, #87, #237 can start immediately. #88 and #239 depend on completions but not each other.
**Critical path:** #384#385#386#392. All content work is blocked until these complete.
**Parallel work:** #404 and #406 are independent and can start immediately.
## PR Workflow