Skip to content

Palimpsest Roadmap

Remembering beats optimizing. Causality beats complexity. Permissions beat modifiers.

Status: Active Last Updated: 2026-01-04


Core Identity

Palimpsest is a narrative memory engine with an interpreter.

We optimize for continuity, causality, and recall — not tactical simulation or build math.

North Star

Every new system must increase narrative continuity density (remembering people/promises/history/consequences) more than it increases mechanical surface area.

If it doesn't improve continuity density, it doesn't ship.


State Type Taxonomy

We do not flatten state into one generic "quality" type. These categories are distinct in schema, tools, and docs:

Category Examples Storage Mutability
Resources Gold, supplies, time budget pc_state, structured fields Fungible, depletable
Conditions Poisoned, wanted, blessed pc_state.conditions[] Flags with constraints
Relationships PC↔NPC tiers, NPC↔NPC links relationship_state, entity_links Tier + history + unlocks
Threads Quests, vows, arcs threads table Stakes, clocks, failure states
Canon Entities NPCs, locations, items, factions entities table Lore in markdown, meta in JSONB
Temporal State Day, time, session campaign_state Pacing + clock triggers

Rule: If a field is queried often, must be validated, or updated atomically → structure it. Everything else stays flexible (markdown + JSONB).


Design Principles

1. Mechanics as Permissions, Not Modifiers

Avoid "+1/-1" bonuses. Prefer: - Unlocks: Access to places, services, information, actions - Behavior shifts: NPC proactive help, refusal, betrayal - Thread generation: Escalations, new complications - Narrative affordances: Special scenes, confidences, invitations

2. Minimal Simulation, Maximal Causality

We do NOT build: - Tactical grid combat - Deep stat/balance systems - Elaborate skill trees - Optimization metas

We DO build: - Persistent consequences - Deadlines/clocks - Relationship memory with reasons - Threads/fronts that move off-screen - Downtime as narrative phase

3. Tooling Constraints

LLM may not silently create canon. New canon requires explicit tool call: - create_entity() gates canonization - resolve_name() prevents freeform IDs - update_relationship() logs reason + clamps tier - advance_clock() requires reason + links to thread

All tool outputs are structured patches, not prose. Server validates invariants.

4. Context Injection Discipline

  • Inject only current state + scene-relevant state
  • Provide 1–2 reasons, not full histories
  • Deep history retrieved via RAG/tool on demand
  • Token budget is a first-class constraint

Phase 1: Relationships

Status: Complete

Problem

NPCs have static disposition labels that decay into flavor text. The LLM needs structured pressure to remember and act on relationship state.

What Becomes Possible

  • NPCs behave differently based on relationship history
  • Reaching +3 (bonded) enables companion promotion
  • Hostile NPCs generate threads against PC
  • Context shows "why" an NPC feels a certain way

Data Model

  • relationship_state(campaign_id, a_type, a_id, b_type, b_id, tier)
  • entity_links for declared NPC↔NPC facts (rivalries, affiliations)
  • vault_events logs changes with reasons

Tools

  • update_relationship(npc_id, delta, reason) → tier change + event log
  • get_npc_relationships(npc_id) → declared links lookup

Context Injection

- **Marlena** (tavern keeper)
  Temperament: welcoming → Toward Jake: **trusted (+2)**
  *Recent: "Helped recover stolen cargo"*
  *Rival of Captain Voss (harbor master bid)*
Budget: ~3 lines per present NPC, max 6 NPCs.

Definition of Done

  • [x] Migration 011 creates relationship_state table
  • [x] update_relationship tool implemented and tested
  • [x] Context builder injects relationship data for present NPCs
  • [x] Seagate campaign backfilled with relationship data
  • [x] Temperament vocabulary migrated (welcoming/professional/cautious/suspicious/hostile)
  • [x] DM system prompt updated with two-layer model

Non-Goals

  • NPC↔NPC mutable tiers (Phase 2+)
  • Relationship decay over time
  • Romance-specific mechanics

Spec: palimpsest-relationship-system.md


Phase 2: Narrative Clocks

Status: Design Draft

Problem

Threads lack urgency. Nothing forces the world to move forward. Players can ignore consequences indefinitely.

What Becomes Possible

  • Threads have visible progress toward resolution or failure
  • Ignoring a threat causes it to escalate
  • Racing against time creates tension
  • World changes even when PC is elsewhere

Data Model

ALTER TABLE rpg.threads ADD COLUMN clock_segments INT;      -- 4, 6, or 8
ALTER TABLE rpg.threads ADD COLUMN clock_filled INT DEFAULT 0;
ALTER TABLE rpg.threads ADD COLUMN if_filled TEXT;          -- Resolution outcome
ALTER TABLE rpg.threads ADD COLUMN if_ignored TEXT;         -- Escalation behavior

Tools

  • advance_clock(thread_name, segments, reason) → progress + event log
  • set_clock(thread_name, segments, filled) → initialize/reset

Context Injection

### Active Threads
- **[URGENT]** Find the missing shipment [████░░░░] 5/8
  → Next: Check the warehouse district
  → If ignored: Cargo sold, trail goes cold
Budget: Clock visualization adds ~1 line per thread.

Definition of Done

  • [ ] Schema migration adds clock fields to threads
  • [ ] advance_clock tool implemented
  • [ ] Context builder shows clock progress
  • [ ] At least one thread in Seagate has active clock

Non-Goals

  • Automatic time-based advancement (requires session tracking)
  • Clock UI components (chat-only for now)
  • Complex linked/racing clock mechanics

Phase 3: Fronts (Thread Bundles)

Status: Concept

Problem

Individual threads feel disconnected. No sense of larger forces at work. World lacks coherent pressure.

What Becomes Possible

  • Threats grouped into coherent antagonist forces
  • Shared "dark future" if front succeeds
  • Escalation cascades across related threads
  • Off-screen world motion feels organic

Data Model

CREATE TABLE rpg.fronts (
  id UUID PRIMARY KEY,
  campaign_id UUID REFERENCES rpg.campaigns(id),
  name TEXT NOT NULL,
  scarcity TEXT,       -- hunger, fear, ambition, decay, etc.
  dark_future TEXT,    -- What happens if front "wins"
  impulse TEXT,        -- Default off-screen behavior
  status TEXT DEFAULT 'active'
);

ALTER TABLE rpg.threads ADD COLUMN front_id UUID REFERENCES rpg.fronts(id);

Tools

  • create_front(name, scarcity, dark_future, impulse)
  • link_thread_to_front(thread_name, front_name)

Context Injection

### Active Fronts
**The Scarlet Syndicate** (scarcity: ambition)
  Dark future: Syndicate controls the docks
  Threads: Missing shipment, Marlena's debt, Harbor master election

Definition of Done

  • [ ] Fronts table created
  • [ ] Threads can link to fronts
  • [ ] Context builder groups threads by front
  • [ ] One front created in Seagate with linked threads

Non-Goals

  • Automatic front escalation rules
  • Front "victory" mechanics
  • Multi-campaign fronts

Phase 4: Downtime

Status: Concept

Problem

No structured way to invest in relationships, projects, or recovery. Time passes but nothing changes off-screen.

What Becomes Possible

  • Explicit "spend time with NPC" action accelerates relationship
  • Long-term projects make progress
  • World clocks advance during downtime
  • Recovery and preparation have narrative weight

Data Model

CREATE TABLE rpg.projects (
  id UUID PRIMARY KEY,
  campaign_id UUID REFERENCES rpg.campaigns(id),
  name TEXT NOT NULL,
  description TEXT,
  clock_segments INT DEFAULT 8,
  clock_filled INT DEFAULT 0,
  status TEXT DEFAULT 'active'
);

Tools

  • start_project(name, description, segments)
  • work_on_project(name, effort, reason) → clock progress
  • spend_time_with(npc_id, activity) → relationship + event
  • advance_time(days) → triggers clock/front advancement

Context Injection

Downtime summary at session start:

### Since Last Session (3 days passed)
- Spent evening with Marlena → relationship +1
- Harbor patrol clock advanced → 6/8
- Repair project → 3/8

Definition of Done

  • [ ] Projects table created
  • [ ] Downtime tools implemented
  • [ ] Time advancement triggers clock updates
  • [ ] Downtime summary in context injection

Non-Goals

  • Calendar/scheduler UI
  • Persona-style social sim mechanics
  • Automatic downtime resolution

Anti-Patterns (Reject Immediately)

Proposals that: - Add crunch without improving memory - Create parallel sources of truth - Depend on hidden inference instead of explicit state - Balloon system prompt instead of improving data + tools - Require optimization or build math - Add tactical combat mechanics


Future Considerations (Not Scheduled)

These may be worth exploring after Phase 4, but only if they pass the continuity-density test:

  • Character Transformations: Scars, blessings, curses as event-sourced canon
  • Legacy Hooks: Retired characters, descendants, reappearing NPCs
  • Multiple Interpreters: Same vault, different "game modes" (mystery, horror, romance)
  • Companion System: Promoting +3 bonded NPCs to party members
  • Faction Relations: PC reputation with groups, not just individuals

References