maniator / maniator/verticopolis

[P2] Settle what session_end measures across the three clock origins (web, desktop returning, desktop first run)

Open
#808 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
5
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Raised by Codex on PR #802 (src/telemetry.ts:88) and deferred there after verification. The mechanism is real; the one-line fix it suggested is not the right shape, for the reasons below.

What is true

startGameplaySession() is called at src/bootstrap.ts:153, before await prepareSaveStore() at :171 and before create() at :173. The clock has no first-activity gate: begin() sets resumedAt = Date.now() (src/analytics.ts:137-139) and end() accumulates from it (:274-277), so the pre-hydration window is inside the reported session_end seconds.

On desktop that window is a real IPC bridge (getPlatform().saveStore, bound only for wrapped modes) that a browser build does not have; web statically folds bootstrap.ts:171 out. BOOT_STORE_TIMEOUT_MS = 3000 (src/game/desktopSaveHydrate.ts:31).

What was overstated

"Each phase and each record read can wait up to three seconds" is true per call but implies a compounding the code prevents. A dead bridge exits early at desktopSaveStore.ts:103 and costs 3s flat, and a timed-out record read aborts hydration at desktopSaveHydrate.ts:208 rather than continuing through all six sources. Only the reconcile-write loop can accumulate, and only when local caches moved ahead of the store.

Realistic healthy cost is 5-50ms, below the metric's own Math.round(activeMs / 1000) granularity. Stalled-bridge cost is ~3s, which is material only against the short tail (measured from session_end over 90 days, web: p10 3s, p25 12s, p50 70s).

Not a regression

src/bootstrap.ts is not in PR #802's diff. The ordering is exactly what is on main; the consent gate only made desktop analytics reachable.

Why the suggested fix is wrong

Moving only the desktop clock past hydration would define desktop session_end as "time after the app was ready" while web keeps "time from boot": two meanings under one metric name. A uniformly slightly inflated metric is better than a per-platform one.

It would also erase the signal for the sessions that matter most here: a player who hits a 3s stall and quits at 4s would report ~1s instead of ~4s.

The actual question to settle

session_end already has THREE different clock origins, and the largest gap is deliberate:

  1. Web: boot, with nothing awaited before create().
  2. Desktop, returning + consented: boot, plus 0-3s of hydration.
  3. Desktop, first run: not at boot at all. startGameplaySession early-returns while consent is pending (src/analytics.ts:477); the session is armed by armSessionOnGrant when the player dismisses the notice (src/ui/uiDesktopAnalytics.ts:71-72, called at :115 and :173), after first paint and after however long they spend reading it. That offset is seconds to minutes.

Fixing (2) while leaving (3) is straining a gnat.

Preferred resolution

Either:

  • (a) Record boot/hydration duration as its own event property so the pre-play window is measurable and subtractable on both editions, keeping one clock origin; or
  • (b) Make an explicit, documented decision about what session_end means across the three cases above, and align them.

Do this when desktop sessions actually start arriving, since (3) dominates and cannot be evaluated without real first-run data.

If a stopgap is ever wanted, the minimal version is moving bootstrap.ts:153 to between :171 and :173 (after hydration, still before app construction so a create() throw leaves the session armed). Do not take it without settling the comparability question first.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the three session-start paths in src/bootstrap.ts, src/analytics.ts, and src/ui/uiDesktopAnalytics.ts, including hydration in src/game/desktopSaveHydrate.ts and the save-store bridge. First compare the existing clock origins with the 90-day session_end data. Done means an explicit, documented cross-platform definition is chosen and either the metric is aligned or boot/hydration duration is recorded separately.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
analytics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.