---
phase: 06.3
plan: "05"
subsystem: diagnostics
tags: [client, spawn-delay, reconnect, telemetry]
requires:
  - phase: "06.2"
    provides: "D-53 spawn-in delay implementation"
provides:
  - "window.__rebno.spawnDelayTicks and spawnDelayTicksTotal telemetry"
  - "ensureLocal reconnect reinitialization audit for plan 06.3-16"
affects: [phase-06.3, D-53, PlayerRenderer, GameScene]
tech-stack:
  added: []
  patterns: ["Unconditional staging-visible window.__rebno diagnostic publish"]
key-files:
  created: []
  modified:
    - apps/client/src/render/PlayerRenderer.ts
key-decisions:
  - "Confirmed the same-GameScene reconnect path reuses PlayerRenderer and does not reset spawnDelayTicks."
patterns-established:
  - "Spawn-delay diagnostics publish the current countdown and fixed total immediately after decrement."
requirements-completed:
  - REQ-CLI-04
  - REQ-CLI-08
duration: 10 min
completed: 2026-05-14
---

# Phase 06.3 Plan 05: D-53 Spawn Delay Telemetry and Reinit Audit Summary

**Spawn delay countdown is now visible in staging devtools, and the reconnect reset bug path is documented for 06.3-16.**

## Performance

- **Duration:** 10 min
- **Completed:** 2026-05-14
- **Tasks:** 2
- **Files modified:** 1

## Accomplishments

- Added unconditional `window.__rebno.spawnDelayTicks` publication immediately after the local spawn delay decrement in `onSimulationTickLocal()`.
- Added `window.__rebno.spawnDelayTicksTotal = 30` so operators can compare countdown progress to the legacy 30-tick hold.
- Audited `ensureLocal()` and `GameScene.onLocalJoin()` to identify which reconnect path skips reinitialization.

## Reinit Audit Finding

- `PlayerRenderer.ensureLocal()` returns early when `this.local` already exists (`apps/client/src/render/PlayerRenderer.ts:127`), so it does not reinitialize `spawnDelayTicks` on an existing renderer.
- Fresh local creation initializes `spawnDelayTicks: 30` in `ensureLocal()` (`apps/client/src/render/PlayerRenderer.ts:147`) and in the fallback `setLocalPosition()` allocation path (`apps/client/src/render/PlayerRenderer.ts:165`).
- `GameScene.create()` allocates a new `PlayerRenderer` once per scene (`apps/client/src/scenes/GameScene.ts:168`).
- `GameScene.onLocalJoin()` calls `this.playerRenderer?.ensureLocal(...)` on the existing renderer (`apps/client/src/scenes/GameScene.ts:468`).
- Path A confirmed: websocket reconnect within the same `GameScene` reuses `PlayerRenderer`, hits the early return, and does not reset `spawnDelayTicks`.
- Path B confirmed: force-reset/LoginScene/new `GameScene` creates a new `PlayerRenderer`, so `spawnDelayTicks` resets correctly.

Decision passed to `06.3-16`: add a `PlayerRenderer.resetSpawnDelay()` method or equivalent and call it from the local-join path so same-scene reconnects restart the 30-tick hold.

## Task Commits

1. **Task 1/2: Spawn delay telemetry and audit** - `bf0e121` (`spike(06.3-05)`)

## Files Created/Modified

- `apps/client/src/render/PlayerRenderer.ts` - Published `spawnDelayTicks` and `spawnDelayTicksTotal` after each countdown decrement.

## Decisions Made

- Kept the telemetry write inside the existing `spawnDelayTicks > 0` branch so it represents the active countdown window without adding behavior after the hold finishes.

## Deviations from Plan

None.

## Verification

- `pnpm --filter @rebno/client test --run` - PASS, 26 test files passed, 190 tests passed, 4 todo.
- Acceptance grep confirmed the telemetry write is unconditional, has no DEV gate, and publishes `spawnDelayTicksTotal: 30`.

## Next Phase Readiness

Ready for `06.3-16` D-53 reconnect reset fix. The expected test target is spawn, simulate same-scene reconnect, then assert the local renderer countdown resets to 30.

---
*Phase: 06.3*
*Completed: 2026-05-14*
