Skip to content

Notifications — meaningful-state firing + Pratchett-warm Cech editorial voice

D-026: Notifications — meaningful-state firing + Pratchett-warm Cech editorial voice

Pick 13 from the 2026-05-21 vision verification session (Round 4 Pass A). D-021 §3 deliberately deferred notifications — “D-021 does NOT mandate push notifications for either window. Notification cadence, quiet hours, and time-of-day suggestions are W-level (ui-designer + tech-architect, post-D-021).” D-026 closes the deferred surface: not whether the app notifies (player consent), but which classes of state transition are notification-worthy when consent is granted, and in what voice.

D-026 is conditional on player consent. A Walker who grants zero notification permissions experiences the full game with no degradation — D-021 §3’s “notifications NOT prescriptive” promise stands intact. The six-channel structure (§5) and quiet-hours defaults (§6) apply only to channels the player has opted into; nothing in D-026 requires any class be on.

D-level because the firing matrix cross-cuts every quest, every region, every social surface, and the voice constraint shapes ~324 hook lines (108 quests × ~3 beats with notification-class transitions per D-024) authored by narrative-designer in bilingual pairs — ~648 LocalizedStrings minimum, schema-validated. A drift in firing rules or voice register across that volume is uncorrectable post-ship.

1. Firing matrix — six canonical classes

Notifications fire only on meaningful state transitions. Each fire class is canonical; new fire classes require a new D-decision.

#ClassTriggerCross-refPriority
1Quest beat unlockedQuest progresses to a new actionable beat (player has work to do)D-024 §1 (15 main + 3 hidden per region)normal
2Hidden quest revealedAllocated keystone / faction rep / class match unlocks a hidden-quest entryD-024 §3, D-016 keystone unlocknormal
3Encounter queue fulltropy pool at cap; further walking does not add cardsD-020 §3 (badge tiers + queue)normal
4Streak threshold reached7d / 30d / future-canon streak milestonesD-007 §2high
5Regional event spawnedServer-scheduled event window opens in a region the Walker is eligible for — fires exactly once at window open; no impending-close fireD-025 §1, D-022 (map pin)high
6Co-op + guild social transitionsCo-walking session invite / accept; guild @mention; guild event startD-025 §1-2high

Class 3 cadence inheritance: the practical cadence of class 3 inherits from D-020’s tropy pool size cap (B-level under mechanics-designer, deferred at D-020 §What-not-decide). If B-level tuning produces noisy class 3 fires, the remediation is a D-020 pool-cap adjustment, not a D-026 amendment.

Class 6 internal granularity: the three social transitions bundled in class 6 (co-walking session invite/accept, guild @mention, guild event start) MAY be sub-divided as channel sub-options at W-level (per §5 last bullet) without re-opening the canon. Splitting class 6 into separate canonical fire classes (6a/6b/6c) would require a D-decision.

Optional cosmetic-unlock class (deferred): D-028 candidate (cosmetics canon, Round 4 pick 15) will likely add a 7th class for Mapa-theme / Walker-outfit unlocks. D-026 forward-references this without authoring it — if D-028 ratifies, the 7th class slots in without re-litigating the matrix shape.

2. Forbidden fire classes (locked at canon)

Removing these from the design space is half of D-026’s load-bearing work. They will NOT fire as notifications, ever, regardless of future B-level pressure:

  • Streak-decay warnings. The app does not warn the Walker that their streak is at risk. Streaks decay on missed attested days per D-007 §2; no notification, no nag, no countdown. Honours D-008 §4 hardcore-adult audience (the Walker is responsible for their own cadence). Anticipation fires are also forbidden: you-are-1-day-away-from-the-7d-bonus pushes are streak-decay warnings rotated 180 degrees and would re-introduce the nag pattern by the back door. Class 4 fires ONLY on the day the boundary is actually crossed.
  • “Come walk” reminders. No daily activity prompts. No “you haven’t walked today, come back” pushes. Walking is the experience (D-021 §1), not a chore the app polices.
  • Unspent-point nags. Banked tree points sit until the Walker allocates. No notification on accumulation. Allocation is a deliberate evening-session act (D-021 §1, D-018 ~10% per allocation).
  • Empty-queue nags. The encounter queue draining to empty is not a notification class. Walker sees this on next app open; surfacing it as push is anti-Pillar-1 (would push the Walker back to the app instead of to walking).
  • Energy-full / energy-low pings. D-018 ratifies Energy as a tight budget; the player audits Energy in-app, not via push. No “Energy at cap” / “Energy below 1000” pings.
  • Quest-expiration countdowns. D-024 sagas do not expire. No false urgency. Extends to regional-event windows (D-025): events fire ONCE on spawn (class 5); no impending-close countdown fires.
  • Marketing / live-ops nudges. No “new event tomorrow” teasers, no monetization pushes, no Guild Master sub upsells. D-025 regional events fire only on §1 class 5 (event spawned), never as advance hype.
  • Friend / guild-mate activity broadcasts. Notifications fire only on transitions involving the Walker as participant (class 6). Other Walkers’ state changes are not the Walker’s notification surface — no “Marek just unlocked a keystone” pushes, no “Anna started a co-walking session — join her?” broadcasts. Class 6 covers transitions where the Walker is invited / mentioned / participating; observer-mode social broadcasts are not a class.
  • Subscription lifecycle reminders. Apple / Google native subscription-management surfaces handle renewal / lapse / billing-failure notifications at the OS layer; the app does not duplicate them. No “your Guild Master sub expires in 3 days” pushes, no in-app upsell at lapse. Players who let a sub lapse hit the D-008 §3 free-tier cap silently at next sync; that is the affordance, not a re-engagement push.

3. Voice register (canonical)

Default register: Pratchett-warm + light Cech bureaucratic varnish. Honours D-013 (editorial-commit grammar — every notification is a Spis-side observation of state, not an imperative to the player) and D-008 §4 (hardcore-adult audience).

Required qualities:

  • Warm humor; dignity preserved; the player is treated as a competent adult.
  • Observational, not imperative — the notification describes what the Spis just recorded, it does not instruct the Walker.
  • Light editorial varnish: pisarska linijka / Spis przyjął / Cech / linijka oddana do składu register, sparingly. Not every notification needs editorial vocabulary; one in three is the target density.
  • Region-aware where the trigger is region-local (e.g. notification about a Plenny quest beat may reference Plenny by name; a streak milestone is region-agnostic).

Forbidden qualities:

  • Exclamation marks at end. (One mid-sentence exclamation acceptable for Pratchettian effect; never as the closing punctuation.)
  • “Tap to” instructions. The notification IS the surface; tapping opens the app naturally. No „Stuknij, aby otworzyć", no "Open to claim".
  • Emoji of any kind in the notification body. (Channel category icons on Android / SF Symbols on iOS are platform chrome and not part of the body string.)
  • Hype register: no EPIC LOOT WAITING, no all-caps, no 🔥, no NEW! badges in copy.
  • Habit-shaming or guilt: no nie ruszałaś się od trzech dni, no your friends are walking without you.
  • Manipulation: no fake urgency, no fake scarcity, no fake countdowns.
  • Patronizing tutorial register: notifications do not teach. Onboarding handles teaching (D-027 candidate territory).

Reference example (from pick 13 source memo, recorded as canonical voice exemplar — copy-edit by narrative-designer at W-level authoring time):

„Plenny się dziś nie ruszała — może ranek na to za wcześnie?"

Why this works: observational (Spis-side report on regional state), warm (light absurdity of personifying Plenny), no imperative, no nag, no hype. The voice register §3 ratifies applies equally to push notifications (fire matrix §1) AND in-app digest copy (app-open summary, next-sync recap) — the example illustrates voice for both contexts. Note this specific exemplar is daily-summary register, NOT a “come walk” push (which would fall under §2 forbidden); the next-sync digest pattern is permitted, the push-out-of-nowhere pattern is not.

4. Localization rule (D-011 generalised to notification surface)

Notifications are chrome per D-011’s definition:

  • Notification title: ENG by default (per D-011). When the title references a quest, it uses Quest.name.en. Title field is single-locale ENG to keep notification-tray width predictable across font scales.
  • Notification body: Bilingual per player locale (LocalizedString.{pl,en}). Player’s selected app locale governs which body string the OS renders. Pratchett-warm voice + Cech varnish applies in BOTH locales — narrative-designer transcreates, does not translate.
  • Proper-noun toponyms / load-bearing PL concepts in EN body: Permitted via the D-017 glossary mechanism — the EN form registered in the glossary is what surfaces in EN body. When the registered EN form matches the PL form (toponyms like Plenny, load-bearing concepts like Spis, tropy, rejestr), the PL token surfaces as-is. When the registered EN form is a transcreation, that EN form surfaces — narrative-designer’s four-phase pick (D-017) determines which side of this distinction each entity sits on.

This collapses the notification surface to the same locale-separation discipline that already governs in-app chrome (D-011) and the data layer (D-017). No new rule, only the generalisation.

5. Channel structure (canonical: one channel per class)

The fire matrix maps to OS notification channels (Android FCM) / categories (iOS APNs) one-to-one — six channels minimum.

  • Channels MUST map to the six fire classes (one channel per class, minimum). Combining classes into a single channel breaks per-class mute (the player must be able to mute “encounter queue full” without muting “regional event spawned”). The six-channel structure is canonical; collapsing to fewer requires a new D-decision.
  • Streak milestones (class 4), regional events (class 5), social transitions (class 6) are high priority — may bypass DND on Android, may register as time-sensitive on iOS where the user has granted that permission. Quest beat (1), hidden quest (2), encounter queue (3) are normal priority — respect DND, respect quiet hours.
  • W-level may add channel-level sub-options (e.g. mute encounter queue at night) but cannot collapse the six-class structure into fewer channels.

6. Quiet hours / cadence cap (canonical defaults)

D-021 §3 deferred quiet-hours UX to W-level. D-026 ratifies the defaults; W-level owns the configuration surface.

  • Default quiet hours: 22:00 – 08:00 local time (player-configurable). High-priority classes (4/5/6) may pierce quiet hours; normal-priority classes (1/2/3) may not. The pierce posture is canonical — class 4-6 are time-bounded social/state transitions that lose meaning if delayed past quiet-hours end; class 1-3 are not.
  • Cadence cap (class 1 only): no more than 5 quest-beat (class 1) notifications per rolling 24h window (not calendar-day, not fixed UTC reset — rolling smooths bursts and prevents the midnight-double-burst edge case where a 5-fire burst at 23:55 chains into another at 00:05). Bursts beyond 5 in any rolling 24h period coalesce into a single “Several beats are waiting in the Spis” digest. Other classes (2-6) do NOT coalesce — each is its own state transition with its own narrative weight. The class-1-only cap is canonical; extending coalescing to other classes requires a new D-decision.

Specific UX surface for configuring quiet hours / cadence cap (settings page layout, time-picker, override toggles per class) is ui-designer W-level.

Rejected alternatives

  • All-class default-on + opt-out per class. Rejected — hardcore-adult audience per D-008 §4 expects sparse-by-default. Notifications opt-in per class is the correct default; bulk-on imports a mobile-game pattern WalkRPG is positioned against.
  • “Come walk” daily reminder as an optional notification. Rejected — even opt-in, the existence of the class signals the design accepts habit-policing as a UX role. D-021 §1 walking is the experience, not a chore enforced by push.
  • Streak-at-risk warning notification. Rejected — partly because nag-mechanics conflict with hardcore-adult positioning, partly because D-007 §2’s streak invariant already protects honest Walkers (decay on missed attested day means a day with attested walking ALWAYS counts; a player whose streak is “at risk” simply has not walked that day, and a push notification doesn’t change that fact).
  • Notification body in single canonical locale (PL only or EN only). Rejected — D-011 already established the locale-separation discipline (chrome ENG, prose locale-bound); bilingual body extends prose treatment to notification body. The Walker reading Polish UX deserves Polish notifications; the Walker reading English UX deserves English notifications transcreated to preserve voice.
  • Encounter-queue-empty as a notification class. Rejected — would push the Walker back to the app instead of to walking. Pillar 1 inversion.
  • Marketing / event-teaser class. Rejected — D-025 regional events fire on actual spawn (§1 class 5), not on advance hype. The product positioning (D-008 §4) does not tolerate live-ops nudges that interrupt the Walker’s life for revenue reasons.
  • Fewer than six channels (collapsed gameplay/streak/social grouping). Rejected — per-class mute granularity is the hardcore-adult-positioning lever. A player who hates encounter-queue noise must be able to silence it without silencing hidden-quest reveals; coalescing classes 1+2+3 into a “gameplay” channel removes that granularity at the OS layer, where adding it back requires app-level shadow toggles that drift from the OS native pattern.
  • No default quiet hours (opt-in only). Rejected — hardcore-adult positioning expects sane defaults. 22:00 – 08:00 is the global mobile median; shipping with quiet hours OFF reads as oversight, not autonomy.

What D-026 does NOT decide (delegated)

  • Specific copy lines for the ~324 quest-beat hooks — narrative-designer W-level, authored alongside per-quest authoring under D-024.
  • Specific copy for the streak threshold notifications (7d, 30d; future canonical thresholds if/when extended beyond D-007 §2) — narrative-designer W-level.
  • Per-class default opt-in / opt-out posture at first install — ui-designer W-level. Recommended default per D-008 §4: all classes start opt-out; player opts in during onboarding (D-027 candidate). Final call deferred.
  • Quiet-hours UX surface (settings page layout, time-picker, override toggles per class) — ui-designer W-level.
  • Cadence-cap coalescing copy (“Several beats are waiting in the Spis” exemplar above is provisional; narrative-designer owns the final copy) — narrative-designer W-level.
  • Channel naming on Android FCM / category labels on iOS APNs — narrative-designer + ui-designer joint W-level. Must be bilingual where the OS surfaces the name to the player.
  • Notification body length cap (Android typically 240 chars body, iOS varies) — ui-designer + narrative-designer joint W-level. Voice register must survive truncation.
  • Notification with a deep-link payload (open app directly to the relevant quest beat / map pin / encounter card vs open to Home) — ui-designer + mobile-developer joint W-level.
  • A/B testing of notification timing — explicitly FORBIDDEN at B-level. Hardcore-adult positioning per D-008 §4 does not tolerate experimentation on notification cadence; if D-026’s defaults underperform, that is a D-decision to re-litigate, not a B-level toggle.
  • Watch notification surface (Phase 16) inherits §1 firing matrix + §3 voice register but renders condensed (title + short body) per platform constraints — mobile-developer + ui-designer joint W-level at Phase 16.

Forward-references

  • D-027 candidate (Onboarding): will likely introduce the per-class opt-in moment during the diegetic Bertranda walkthrough (Round 4 pick 14). When D-027 ratifies, the opt-in flow lives there; D-026 only ratifies what fires, not when the player chooses to receive what.
  • D-028 candidate (Cosmetics): likely adds class 7 (cosmetic-unlock fire) to the matrix. Editorial amendment to §1, not supersession.
  • Streak-threshold extension D-decision (future, if more than 7d / 30d are added): would expand class 4 trigger list. D-026’s class structure absorbs the extension without re-litigation.

Reasoning

The notification surface is, per game-director’s Round 4 triage estimate, the single biggest copy obligation outside quest prose — ~324 hook lines bilingual = ~648 LocalizedStrings minimum. Authoring that volume without a canon firing matrix risks per-quest drift in what fires, and without a canon voice register risks per-quest drift in how it reads. Both drifts are uncorrectable at scale post-ship.

The firing matrix (§1) and forbidden classes (§2) are designed in tandem — what fires AND what never fires. Closing the forbidden-class list at canon is the load-bearing move: B-level pressure to add “come walk” reminders or “streak at risk” warnings will arise (it always does on retention-driven mobile products), and D-026 closes that door at the canon layer so the conversation does not need to be re-litigated at every product review.

The voice register (§3) operationalises D-013’s editorial-commit grammar at the notification surface: the Spis observes; the Walker acts. This inversion (notification as Spis-side report, not player-side imperative) is what makes the surface feel native to the lore rather than grafted on. The reference example („Plenny się dziś nie ruszała — może ranek na to za wcześnie?") demonstrates the inversion concretely — Plenny is the subject, the Walker is the addressee but not the agent being commanded.

The localization rule (§4) is the cheapest possible generalisation — D-011’s quest-chrome rule already governs in-app surface; extending it to notification chrome requires no new mechanism, only the ratification that the rule applies here too. Players running EN locale receive Pratchett-warm EN with PL toponyms via the D-017 glossary; players running PL locale receive the same voice transcreated, not translated.

The six-channel structure (§5) and quiet-hours / cadence-cap defaults (§6) are the operational scaffolding — together they bound the OS-layer surface so W-level can author the configuration UX without re-litigating the per-class mute granularity, the high-vs-normal priority split, or the quest-beat coalesce cap.

Source: pick 13 from ops/memory/vision-qa-2026-05-21.md. Triage by game-director (2026-05-21 Round 4 estimate). Pre-ratification recon per [[feedback-decide-triage-recon]] confirmed “notification” has zero presence in data/src/content/; “hook” in data/ refers exclusively to narrative forward-references in quest prose, not notification-system terminology — no collision. Three CEO call-out picks at ratification: §5 six-channel granularity (recommended), §6 22:00–08:00 quiet hours with high-priority pierce (recommended), §6 cadence cap class-1-only at 5/24h (recommended). All three recommended-win. system-reviewer verdict PASS_WITH_NITS at 2026-05-21; all 9 nits applied inline pre-commit (review file: ops/reviews/D-026-notifications-canon.md).