Allows resetting the LLM stats aggregation window without deleting
historical data. Stores a reset timestamp in metadata and filters
the aggregation query to only include calls after that point.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When NPCs emergency-sleep during the day, they now take a short nap
instead of a full sleep. They wake with just enough energy to reach
nightfall, naturally resynchronizing to a nocturnal sleep schedule.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix inverted guard logic (napTarget < 60 triggers full sleep, not >=),
add cycleTicks derivation, clamp napTarget to 100, add test plan.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add berry plant tileset (growing/ripe/picked phases) and wire berry bush
state from server to client so plants visually update as NPCs forage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove pointsOfInterest from WorldState type, state serializer,
and client rendering. Remove foodPositions from map generator
interface and output. Update stale comment in worldSerializer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add drink/forage to isTargetBusy in socialSystem so NPCs drinking or
foraging are not interrupted by social interactions. Add drink/forage
to the industry system goal skip list so it doesn't override those goals.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When an NPC has the 'forage' goal, gathered berries restore hunger
and gathered water restores thirst directly (+20) instead of going
to inventory. Berry bush depletion still occurs. Goal resets to null
after consumption so npcBrain can re-evaluate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Eating now consumes berries from inventory or nearby stockpile instead of
recovering hunger for free. Added drink goal (consumes water) and forage
goal (desperate survival gather when no food/water available). Priority
order: sleep > eat > drink > forage > dropoff > gather > wander.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace foodPositions with berryBushes in TileData, saving per-bush
berryCount, maxBerries, and ticksSinceLastRegrowth to the metadata table.
On load, restore berry bush state into GameMap; fall back to initializing
from resource tiles for old saves without berry data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace magic food POI system with berry bush clusters as gatherable
resource tiles. Berry bushes track depletion state (berryCount, maxBerries,
ticksSinceLastRegrowth). Remove PointOfInterest interface and all POI
methods from GameMap, stub out closestPOI in npcBrainSystem for later
rework, and update all tests and serializers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TDD-structured plan covering thirst need, berry bushes, hunger rework,
forage goal, UI bars, and food POI removal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Berry bushes as gatherable food, thirst need consuming water items,
productivity bar on status tab, desperate forage goal, remove magic
food POIs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Constants were purely in-memory; any server restart reverted them
to code defaults. Now saved to metadata table as JSON on every
autosave and restored on startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Default 200→400, invention 300→600, desireGeneration 500→800,
backstoryAndDesires 800→1200. Can trim back once we have usage data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MODEL_PRICING keys were 'gpt-oss-120b' but the actual model string
from env is 'openai/gpt-oss-120b'. The lookup always missed, so
calculateCost returned 0 for every call. Updated keys to match the
full OpenRouter model identifiers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Templates with jsonResponse:true automatically get the compact
single-line JSON instruction appended to their system prompt via
renderTemplate. Removes manually duplicated JSON formatting
instructions from invention, backstoryAndDesires, and desireGeneration
templates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Model sometimes returns pretty-printed JSON with newlines/indentation,
wasting tokens and causing truncation. Now requests compact single-line
JSON. When JSON is truncated, regex-extracts the backstory field rather
than setting raw JSON as the backstory text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Post-restart logs show model still hitting 600-token ceiling on verbose
responses — truncated JSON at exactly 599-600 output tokens. Average
successful response was ~418 tokens but outliers reach 600+. Added
explicit conciseness instructions to backstory prompt to reduce variance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every single LLM failure was finish_reason='length' — the model was
running out of output tokens before completing the JSON response.
backstoryAndDesires at 350 tokens couldn't fit a backstory + 2 desires
with fulfillment criteria; desireGeneration at 250 was too tight for
a single desire with reasoning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Captures full prompt content, response text, HTTP status, and finish
reason on every LLM failure path. Replaces silent null returns in
openRouterClient with structured CompletionFailure objects so error
details propagate up through the queue and service layers.
Also removes recipeList from backstoryAndDesires prompt (not useful
for backstory generation) and adds schema migration v3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every failure path was silent — LLM nulls, parse failures, validation
rejections, and promise errors were all swallowed. Adds per-attempt
logging at each gate plus a periodic summary of NPC/inventory/item state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix LLM stats panel stuck on "Loading stats..." by requesting stats
immediately after admin authentication succeeds
- Add retry mechanism for backstory generation (up to 3 attempts with
increasing delays) so transient failures don't permanently skip NPCs
- Fix stale model bug: queued LLM requests now use the current model at
dequeue time instead of capturing it at enqueue time, so fallback
model switches take effect for pending requests
- Add per-template maxTokens (backstory: 350, invention: 300, desire:
250) to prevent "length" finish truncation on structured JSON responses
- Remove unused "reasoning" field from backstory prompt to reduce token usage
- Add failure logging throughout LLM pipeline (backstory null results,
queue errors) for better diagnostics
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract shared WORLD_PREAMBLE and prepend to all system prompts
- Remove duplicated world-setting text from individual templates
- Add server/saves/ and treesnstone.zip to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>