# Phase 06.4: cycle-5 gap-closure - Discussion Log

> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

**Date:** 2026-05-15
**Phase:** 06.4-cycle-5-gap-closure
**Areas discussed:** D-63 helper API + constants module, D-62 mvp-room data fix, D-60 spike-vs-direct, Re-confirm items workflow

---

## Area 0 — Gray-area selection

| Option | Description | Selected |
|--------|-------------|----------|
| D-63 helper API + constants module | Where helper lives; constants source; signature; refactor scope | ✓ |
| D-62 mvp-room data fix — defensive or strict | Data fix / schema strict / server defensive / fail-loud | ✓ |
| D-60 spike-first vs direct fix | Hypothesis unverified; ship vs spike tradeoff | ✓ |
| Re-confirm items workflow | D-51b/D-55b/D-57b/D-58b handling — plan / verification only / skip | ✓ |

**User's choice:** All four selected (multiSelect).

---

## D-63 helper home

| Option | Description | Selected |
|--------|-------------|----------|
| New file `apps/client/src/render/legacy-origin.ts` | Helper + constants co-located, render-only | ✓ (discretion) |
| Extend `PlayerRenderer.ts` | Minimize file count | |
| Promote to `packages/protocol` or `packages/game-logic` | Cross-package, future-proof | |

**User's choice:** "agent decides using best judgment"
**Notes:** Render-only concern, packages/* promotion premature; PlayerRenderer.ts already large.

---

## D-63 constants source

| Option | Description | Selected |
|--------|-------------|----------|
| Hardcoded constants with source cite | Simple; drifts silently | |
| Read from atlas-mvp.json at boot | Self-syncing; adds boot dep | |
| Hardcoded + unit test asserts atlas matches | Runtime simple, CI drift catch | ✓ (discretion) |

**User's choice:** "agent decides using best judgment"
**Notes:** Matches 06.3 GREEN-gate canonical-ref discipline.

---

## D-63 helper signature

| Option | Description | Selected |
|--------|-------------|----------|
| Object-in, tuple-out (matches roadmap) | `spec → [originX, originY]`; destructure into setOrigin | ✓ (discretion) |
| Object-in, object-out | `spec → {originX, originY}`; less ergonomic | |
| Curry: helper returns binding fn | Composable for batch ports; premature | |

**User's choice:** "agent decides using best judgment"
**Notes:** One consumer in 06.4; tuple destructures cleanly into `setOrigin(...)`.

---

## D-63 refactor scope

| Option | Description | Selected |
|--------|-------------|----------|
| Only startTeleportAnim (D-55c fix) | Tight 06.4 scope | ✓ |
| Add lint rule blocking inline math | Brittle; false-positives | |
| Refactor any grep-found call site | Discovery work; scope creep risk | |

**User's choice:** Only startTeleportAnim (D-55c fix)

---

## D-62 mvp-room fix path

| Option | Description | Selected |
|--------|-------------|----------|
| Data fix + schema enforcement | Patch JSON + require fields in schema | |
| Data fix only | Patch JSON; future rooms can recur bug | |
| Data fix + server defensive synthesis | Belt + suspenders runtime fallback | |
| Schema-strict only, fail-loud | Reject non-conforming rooms at load | |
| **Server-runtime derive + broadcast (user proposed)** | Derive collision_polys + room_size from tiles[] on server, broadcast as part of s2c.room_layout | ✓ |

**User's choice:** Operator proposed: "couldn't we have each room's collision polys generate i.e. at compile time or runtime, derived from the room's floor tiles layout?" → Server-runtime derive + broadcast selected.
**Notes:** Phase 7 deferred = compile-time codification + mixed-walkable/abyss handling. MVP rooms (uniform floor) work cleanly with bbox derivation.

---

## D-60 fix path

| Option | Description | Selected |
|--------|-------------|----------|
| Direct fix — always emit room_layout on onJoin | Idempotent; minimal blast radius | ✓ |
| Spike-first — telemetry then fix | Safer; one extra Wave cycle | |
| Spike + direct fix bundled | Single plan; risks no-op if hypothesis wrong | |

**User's choice:** Direct fix — always emit room_layout on onJoin

---

## Re-confirm items workflow (initial)

| Option | Description | Selected |
|--------|-------------|----------|
| Single verification plan (no new code) | Operator UAT-only on 4 cycle-2 commits | |
| Full plan per fix with regression test | Heavier; quadruples plan count | |
| Skip plans entirely (verification only) | Lightest; no anti-recurrence test | |
| **Operator tested live during discuss-phase** | Test now, capture results | ✓ |

**User's choice:** Operator tested live. Results:
- D-51b: **FAIL** — both tabs freeze + looping "reconnected" banner ~5s cadence. New symptom worse than cycle-4. Re-open as D-51c.
- D-55b: **PASS** (anim swap) but D-55c (origin misalignment) still broken AND new D-55d found (TeleIn fires for all already-present remotes on session start).
- D-57b: **PASS**
- D-58b: **PASS** for position, but new D-58c surfaced (direction state desyncs — local StandingR vs remote StandingUR).
- Bonus D-45d: nametag still flickers + intersects on remote moving players despite 06.3 Plan A + B work.

---

## Re-confirm workflow v2 (post-UAT)

| Option | Description | Selected |
|--------|-------------|----------|
| Treat D-51c/D-55d/D-58c/D-45d as full new defects (Recommended) | Each gets own plan; spike-or-direct per defect; add regression tests for D-57b/D-58b PASS | ✓ |
| Fold into existing D-51/D-55 scope without new IDs | Simpler ID space; loses surface visibility | |
| Escalate D-51 to its own phase (06.5) | D-51 failed 3 cycles; deserves dedicated phase + Colyseus version-bump investigation | |

**User's choice:** Treat D-51c/D-55d/D-58c/D-45d as full new defects (Recommended)

---

## Claude's Discretion

- D-63 helper home: `apps/client/src/render/legacy-origin.ts`
- D-63 constants source: hardcoded + atlas drift test
- D-63 helper signature: object-in, tuple-out

## Deferred Ideas

- Colyseus 0.17 → 0.18 upgrade (escalate if D-51c spike points here)
- Compile-time `collision_polys` codification (Phase 7 with AST-* asset pipeline)
- Mixed-walkable / abyss / fall-tile room support (Phase 7)
- BitmapText / sprite-font glyphs (Phase 7 — durable D-45 alternative)
- Helper expansion to HexportIn/Out, ncol*, jokershell, ChtCmd*, watching overlay (Phase 7 when ported)
- Eslint rule blocking inline (originX, originY) math (revisit if Phase 7 sees recurrence)
