feat(02-05): sim/offline + auto-harvest + letter Ink + letter-renderer
- src/sim/offline/: OfflineEventBlockSchema (Zod) + EMPTY_OFFLINE_EVENTS + aggregateOfflineEvent pure aggregator (D-19); 14 tests green - src/sim/garden/auto-harvest.ts: autoHarvestReadyPlants silent-mode branch (D-10); reuses harvest() pipeline so selector + Pitfall 10 unlocks + STRY-10 Lura gate all run identically; BLOCKER 3 invariant preserved (no lastTickAt writes); 7 tests green - simulateOneTick: ctx.silent triggers auto-harvest sweep before tick increment; active-play path unchanged (silent defaults false) - content/dialogue/season1/letter-from-the-garden.ink: authored skeleton with VAR plants_bloomed / fragment_titles / lura_was_here per D-17/D-18; bible voice, anti-FOMO compliant, 24h cap silent in voice (D-11) - ink-loader: loadInkStory union extended with letter-from-the-garden; separate letterStoryGlob for lazy code-split chunk; INK_VARIABLE_MAP gains plants_bloomed / fragment_titles / lura_was_here slots reading from session.pendingLetterEventBlock - src/ui/letter/letter-renderer.ts: pure buildLetterSlots helper — prefers fragment first-sentence body for tonal weight, slugified-id fallback; 10 tests green - npm run compile:ink emits 5 .ink.json files (was 4); Vite emits the letter as a separate lazy chunk (letter-from-the-garden.ink-*.js) - 295/295 tests green (was 264; +31 new); npm run ci exits 0
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
// Letter from the garden — UX-02 + CONTEXT D-17 + D-18 + D-20.
|
||||
//
|
||||
// Composed from authored skeleton + templated insertions per CONTEXT D-17.
|
||||
// Slots populated at runtime from sim/offline/events.ts via the variable
|
||||
// map in src/content/ink-loader.ts.
|
||||
//
|
||||
// Per Pitfall 4: Ink VAR names are snake_case AND case-sensitive.
|
||||
// Per CONTEXT D-11: 24h offline cap is silent in voice — no numeric
|
||||
// "28h" copy in any branch.
|
||||
// Per CLAUDE.md Tone — the gardener-keeper voice. Warm. Specific.
|
||||
// Intermittent. Sometimes funny, sometimes devastating. Never a stat
|
||||
// dump (UX-02 explicitly forbids that). The skeleton holds the voice;
|
||||
// the slots fill in the specifics.
|
||||
// Per anti-fomo-doctrine.md: this letter is NOT a "you missed X — come
|
||||
// back tomorrow!" nag. It is a contemplative summary of what stayed.
|
||||
|
||||
VAR plants_bloomed = 0
|
||||
VAR fragment_titles = ""
|
||||
VAR lura_was_here = false
|
||||
VAR fragment_count = 0
|
||||
VAR last_plant_type = ""
|
||||
|
||||
== letter ==
|
||||
|
||||
The garden held its breath while you were gone.
|
||||
|
||||
{ plants_bloomed > 1:
|
||||
{plants_bloomed} blooms came and went, each leaving the soil a little quieter than they found it.
|
||||
- else:
|
||||
{ plants_bloomed == 1:
|
||||
One bloom came and went. The space it left feels generous, somehow.
|
||||
- else:
|
||||
Nothing bloomed. The wind carried something else, and the garden held that, too.
|
||||
}
|
||||
}
|
||||
|
||||
{ fragment_titles != "":
|
||||
Among what stayed: {fragment_titles}.
|
||||
}
|
||||
|
||||
{ lura_was_here:
|
||||
Lura came by once. She did not knock. She left a folded leaf on the gate post — you'll find it when you next walk past.
|
||||
}
|
||||
|
||||
The light is the same as when you left. The garden is older.
|
||||
|
||||
-> END
|
||||
Reference in New Issue
Block a user