From 7d7aec9cec18a071700b63d2039ce8ebd38bc3ea Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Fri, 6 Mar 2026 19:59:24 +0100 Subject: [PATCH] chore(meta): plan Sprint 25: Emerge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generator spike sprint. 5 tickets across copy and server teams: - #609 zone identity spec (copy) - #610 Krenn culture profile (copy) - #611 NpcBlueprint struct design (server) - #612 Template assembly generator (server) - #613 NPC generation pipeline (server) Sprint proof: throwaway render — rural Krenn village from minimal input (zone type + culture profile, no per-location spec). Closed #586 (tile data model epic — child #594 done). Co-Authored-By: Claude Sonnet 4.6 --- docs/backups/settledreach.db.backup | Bin 610304 -> 643072 bytes docs/sprints/sprint-25/copy.md | 60 +++++++++++++++++ docs/sprints/sprint-25/joint.md | 100 ++++++++++++++++++++++++++++ docs/sprints/sprint-25/server.md | 77 +++++++++++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 docs/sprints/sprint-25/copy.md create mode 100644 docs/sprints/sprint-25/joint.md create mode 100644 docs/sprints/sprint-25/server.md diff --git a/docs/backups/settledreach.db.backup b/docs/backups/settledreach.db.backup index 30bdfde72b75d673514a738c21ce0af3def41bad..00b92db41a8748754babce10ad1fd5a25b3117ba 100644 GIT binary patch delta 26074 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 delta 4685 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 for full details. + +## Key Decisions + +- `decisions/scope.md` — D-114 (generator-first proof-of-life), D-119 (generator spike critical path) +- `decisions/content.md` — D-121 (voice is culture-driven, job as modifier), D-122 (all NPCs generated), D-128 (culture implicit in starting location), D-129 (NPC personality: traits + behavior first) +- `decisions/architecture.md` — D-012 (chunk-based map, borderless generation future) + +## Notes + +**#609 — Zone identity spec** + +- Output: a YAML or Markdown document defining zone type taxonomy for the Settled Reach's social vocabulary. +- What each zone TYPE means (not a specific location): urban residential, rural agricultural, industrial transit, informal/fringe, commercial, etc. What does each feel like? Who lives or works there? What emotional register does it carry? What is the density, pace, noise level? +- This is a general taxonomy — NOT a spec for a specific village. The generator needs the zone types as input parameters so it can extrapolate any location. +- Downstream consumers: Tyre (generator zone template parameters for #611/#612), Araminta (zone visual grammar), Mellanie (culture-primary voice cards). +- File location: `content/global/zone-identity-spec.md` (or YAML if preferred — coordinate with Tyre on what format #611 needs to ingest). +- Krenn System context: check `decisions/content.md` D-036 amendment and D-128. Station Sova's districts (D-093) are an example of zone types in action but the spec must generalize beyond Sova. + +**#610 — Krenn culture profile** + +- Output: one full culture profile for Krenn System / Station Sova, usable as generator input constraints and AI content templating prompt seeds. +- Must encode: naming conventions and phonemes, speech patterns and registers (formal/informal), economic values and class markers, attitudes toward work/leisure/authority, sensory palette (what Krenn space looks/smells/sounds like), social norms and taboos, dress and appearance codes. +- D-128: culture is implicit in starting location. This profile IS the cultural context for every generated NPC in the Krenn System — not just flavor text. +- D-121: voice is culture-driven, job modifies. The culture profile must be specific enough that Tyre can use it to constrain generated NPC voice parameters. +- D-123: this profile feeds the AI content templating pipeline. Culture vectors = prompt constraints. The profile must be concrete enough to function as a constraint, not just atmospheric description. +- File location: `content/global/culture-krenn.md` (or YAML — coordinate with Tyre). +- Existing Sova atmosphere notes live in `decisions/content.md` D-036 (amended post-workshop). Pull from those but go deeper on cultural mechanics. + +## Dependency Chain + +``` +#609 (zone identity spec) ──┐ + ├──> server #611 (NpcBlueprint struct) +#610 (Krenn culture profile)┘ └──> #612 (template gen) ──> #613 (NPC pipeline) +``` + +Copy deliverables (#609, #610) are prerequisites for all server work in this sprint. Both can be written in parallel — they are independent of each other. + +## PR Workflow + +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(copy): zone identity spec and Krenn culture profile" --description "body" --base main --head copy +``` diff --git a/docs/sprints/sprint-25/joint.md b/docs/sprints/sprint-25/joint.md new file mode 100644 index 000000000..5f5aec037 --- /dev/null +++ b/docs/sprints/sprint-25/joint.md @@ -0,0 +1,100 @@ +# Sprint 25: Emerge — Joint + +**Goal:** Prove the generator can extrapolate from minimal input — a rural Krenn village from zone type and culture profile alone, no per-location spec. + +## Pre-Sprint + +| Item | Owner | Blocks | +|------|-------|--------| +| Coordinate output format for zone identity spec (#609) | Miri + Tyre | #611 | +| Coordinate output format for culture profile (#610) | Miri + Tyre | #611, #612 | +| Confirm `NpcBlueprint` file location and module wiring | Tyre | #612, #613 | + +The critical coordination question: does copy deliver YAML files (which the generator reads at runtime) or Markdown design documents (which Tyre reads and encodes into Rust)? Either works — decide at sprint start. YAML is preferred if Tyre can define a schema upfront; Markdown if the profile needs to be free-form first and codified later. + +## Sprint Completion Proof — Throwaway Render + +**This is not a test suite. It is an eyeball test.** + +The proof is a single standalone invocation that feeds the generator minimal parameters and inspects the output for shape and coherence. + +**Input (the minimum the generator must accept):** +``` +zone_type: "rural" +region: "outside Sova urban zone" +system: "Krenn" +seed: 42 +``` + +Plus the Krenn culture profile (#610) and zone identity taxonomy (#609) — loaded from disk, not hardcoded. + +**NO location-specific spec.** No "the village has a tavern." No bespoke social site list. The generator extrapolates entirely from zone type + culture. + +**Command (to be written as part of #612):** +```bash +cargo run --bin generator-spike -- --zone rural --seed 42 +``` + +**Expected output (printed to stdout):** +1. `DistrictSkeleton` summary: zone type, block count, social site placements +2. Generated NPC list: one line per NPC with name, role, 2-3 traits, one observable behavior +3. A sample relationship pair (NPC A knows NPC B as X) + +**The pass condition (human judgment, not automated):** +- Does the output have *shape*? A rural area should feel different from an industrial one. +- Does it feel like it *belongs in the Krenn System*? Not generic space-village. Krenn-inflected. +- Can you read the NPC relationships from the output? Not infer — *read*. + +**The fail condition:** +- Output could be from any game in any setting (culture profile not doing work) +- All rural areas produce identical outputs with different names (zone type not doing work) +- NPC traits are unreadable from text (legibility fails — D-129 gate not met) + +**Why this framing matters (from the approval discussion):** +The sprint proof deliberately uses minimal input because the generator's entire value proposition is scaling beyond hand-authored content. If it only works with detailed per-location specs, it fails the brief — because the whole point is the player walking into an unspecified area and it still having shape. The "throwaway render" framing is intentional: this is a rough proof, not a polished demo. Pass/fail is a 5-minute eyeball by the team lead. + +## Tickets by Team + +| Team | # | Title | +|------|---|-------| +| copy | #609 | Zone identity spec | +| copy | #610 | Krenn culture profile | +| server | #611 | NpcBlueprint struct design | +| server | #612 | Template assembly generator | +| server | #613 | NPC generation pipeline | + +## Dependency Chain + +``` +copy #609 (zone spec) ──┐ + ├──> server #611 (NpcBlueprint) ──> #612 (template gen) ──> #613 (NPC pipeline) +copy #610 (culture) ───┘ +``` + +Copy (#609, #610) runs in parallel and completes first. Server (#611 → #612 → #613) runs sequentially after copy delivers. + +## Open Questions + +| ID | Question | Blocking | +|----|----------|---------| +| Q-WTF-033 | AI templating: Claude API, local ollama, or manual for v0.2? | #613, #623 | +| Q-WTF-039 | Character creation screen: portrait render or tile-scale preview? | Sprint 26+ | +| Q-WTF-040 | Do creation choices trace into the generated apartment? | Sprint 26+ | + +Q-WTF-033 is the most relevant to this sprint. #613 does not need to implement AI templating — that is #623 (deferred). But the pipeline should be designed so AI templating slots in later without a rewrite. Discuss at sprint start. + +## Deferred to Future Sprints + +- Tycoon bookmark (#605, #614-617) — needs generator output proven first +- Character creation screen (#606, #618-620) — client work, post-generator +- NPC legibility systems (#607, #621-622) — downstream of generator +- AI content templating (#623) — Q-WTF-033 unresolved +- World feel systems (#608, #624-626) — downstream of everything +- Visual rendering of generated world — out of scope for this spike + +## What This Sprint Does NOT Do + +- No client work (no rendering of generated content) +- No new content authored beyond the zone spec and culture profile +- No AI templating implementation (design for it, don't build it) +- No playable session from the generated world diff --git a/docs/sprints/sprint-25/server.md b/docs/sprints/sprint-25/server.md new file mode 100644 index 000000000..719a9f835 --- /dev/null +++ b/docs/sprints/sprint-25/server.md @@ -0,0 +1,77 @@ +# Sprint 25: Emerge — Server Tasks + +**Goal:** Prove the generator can extrapolate from minimal input — a rural Krenn village from zone type and culture profile alone, no per-location spec. + +**Branch:** `server` +**Agents:** Dudley (simulation dev), Tyre (architect) + +## New Tickets + +| # | Title | Blocked by | +|---|-------|------------| +| #611 | NpcBlueprint struct design | #609 (copy), #610 (copy) | +| #612 | Template assembly generator | #609, #610, #611 | +| #613 | NPC generation pipeline | #611, #612 | + +Use `tooling/db/ticket show ` for full details. + +## Key Decisions + +- `decisions/scope.md` — D-114 (generator-first proof-of-life), D-119 (generator spike critical path), D-115 (skills + bookmark only for creation) +- `decisions/content.md` — D-122 (all NPCs generated), D-128 (culture implicit in location), D-129 (NPC personality: traits + behavior first), D-121 (voice culture-driven), D-123 (AI content templating via culture vectors) +- `decisions/architecture.md` — D-012 (chunk-based map, borderless generation future) + +## What Exists + +- **`server/src/simulation/generator.rs`** (576 lines) — `DistrictSkeleton` data model, `DistrictType`, `ZoningType`, `SocialSitePlacement`, `TriangleAssignment`, `BlockSkeleton`. This is the Phase 1 *data model* — struct definitions for what a generated district looks like. The *generator logic* that produces these structs from input parameters does not yet exist. +- **`server/src/npc/generate.rs`** — existing NPC generator taking a `RoleDefinition` (the 10-axis model: Want, Secret, Relationships, Tolerance, DailyRoutine, InformationInventory, Contentment, PersonalityTraits, TellSystem, SkillSet). Generates a fully-populated NPC entity via `SimRng` (deterministic, seeded). Sprint 25 work extends this pipeline, it does not replace it. +- **`server/src/npc/`** — full NPC component set: `awareness.rs`, `background.rs`, `disclosure.rs`, `generate.rs`, `interaction.rs`, `mod.rs`, `mood.rs`, `relationships.rs`, `routine.rs`, `tell_state.rs`, `tolerance.rs`, `trait_modifiers.rs`, `vision.rs`. +- **`server/src/content/`** — content loading: `entanglement.rs`, `hot_reload.rs`, `instantiation.rs`, `line_pool.rs`, `loader.rs`, `spawn.rs`, `template.rs`, `types.rs`. + +## Notes + +**#611 — NpcBlueprint struct design** + +- Blocked by #609 and #610 (copy team delivers these first). Read those documents before writing the struct. +- This struct is the *interface* between the generator and all downstream systems: rendering, voice, AI templating, simulation. +- Must encode: trait set (from D-129), observable behavior surface (what a bystander can read), relationships (Sims + Rimworld style per D-129), role/occupation, cultural markers (feeds D-121 voice pipeline and D-123 AI templating), zone-type affiliation. +- The existing `RoleDefinition` in `npc/generate.rs` covers the 10-axis model. `NpcBlueprint` is a higher-level generator output that wraps role + cultural context + zone parameters. Think of `RoleDefinition` as "what the generator uses internally" and `NpcBlueprint` as "what the generator exports." +- Write the struct in `server/src/npc/blueprint.rs` (new file). Add a D-record reference in `decisions/architecture.md` or `decisions/content.md` when the struct is settled. +- Must be serializable (Serde) for inspection output (the sprint proof dumps the blueprint JSON to stdout). + +**#612 — Template assembly generator** + +- Blocked by #609, #610, #611. +- Input: zone type parameter (from zone identity spec), culture profile (from Krenn culture profile), seed (u64). No per-location spec. The whole point is extrapolating from minimal input. +- Output: a `DistrictSkeleton` (already defined in `server/src/simulation/generator.rs`) with `SocialSitePlacement` entries populated and `NpcBlueprint`s attached to each role slot. +- NOT procedural geography — template assembly. The generator picks a zone template from the zone identity taxonomy and fills it. The template provides the shape; the culture profile and seed provide the variety. +- Write generator logic in `server/src/simulation/generator.rs` (add below existing structs) or extract to `server/src/simulation/template_assembly.rs` — architect's call. +- The generator must be callable standalone (not as a bevy system) for the sprint proof (see joint.md). +- Determinism: use `SimRng` (ChaCha20, existing in `server/src/simulation/rng.rs`). Same seed + same zone type + same culture profile → same output. + +**#613 — NPC generation pipeline** + +- Blocked by #611 and #612. +- Wire the template generator output into actual NPC entity spawning. +- Input: `DistrictSkeleton` with `NpcBlueprint`s → spawn ECS entities using the existing `npc/generate.rs` pipeline, extended to accept cultural markers from the blueprint. +- The existing `RoleDefinition` in `npc/generate.rs` needs a cultural marker field (or the blueprint drives trait selection to match the culture profile). +- Proof-of-life test (in the sprint proof): print generated NPC trait sets and observable behaviors to stdout. A human reading the output should be able to say "yes, this NPC could plausibly exist in the Krenn System." +- D-129: traits + behavior first. The proof gate is not rendering — it is legibility from text output alone. + +## Dependency Chain + +``` +copy #609 (zone spec) ──┐ + ├──> #611 (NpcBlueprint) ──> #612 (template gen) ──> #613 (NPC pipeline) +copy #610 (culture) ───┘ +``` + +Server work begins when copy delivers #609 and #610. #611 must be complete before #612 starts. #613 follows #612. + +## PR Workflow + +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(simulation): generator spike — NpcBlueprint, template assembly, NPC pipeline" --description "body" --base main --head server +```