Skip to content

hot-reload: apply response gives no signal when a patched method is reachable only from an already-run one-shot lifecycle path #2396

Description

@hatayama

Background

Reported independently by two testers in usability-feedback Round 26 (and once in Round 25). Both patched a method that is called only from Awake():

  • GameBootstrap.BuildPlayer() (adding a player.layer = ... line)
  • TetrisGameController.SetUpCamera() (camera tuning)

The apply response was:

{
  "Kind": "Patched",
  "Reason": "",
  "InvocationCount": 0,
  "LifecycleNote": ""
}

with Success: true and "Hot reload applied.". Everything stated is true, but nothing tells the caller that the patched body will never run in the current Play session because its only caller (Awake) has already executed.

One tester burned 3 extra round trips: Stop/Play to re-run Awake → the Play-entry domain reload dropped the patch → re-applied per the guidance ("re-apply uloop hot-reload after Play Mode starts") → still no effect since Awake had already run again → finally compile + Play solved it.

Current documented behavior (not a bug)

LifecycleNote is set only when the patched method itself is a one-shot lifecycle message (private void Awake/Start/OnEnable/OnDisable/OnDestroy on a MonoBehaviour) — see LifecycleNotes.cs and the SKILL.md field description ("empty otherwise"). Methods merely called from such messages get no note. --status already explains InvocationCount: 0 on Active rows, but the apply response does not.

Proposal

Either (or both):

  1. Caller-aware note: when a patched method's only same-assembly callers are one-shot lifecycle messages, populate LifecycleNote with wording like "reachable only from already-run one-shot lifecycle paths; the patched body will not run in this Play session — run uloop compile and re-enter Play Mode to observe it." A conservative fail-open analysis (emit nothing when uncertain) keeps the field truthful. A precedent for same-assembly callsite analysis exists in the pause-point physics-callback warning.
  2. Cheap generic fallback: a note on any Patched row whose method is still at InvocationCount: 0 when the next reload (or Play re-entry re-apply) happens — "this method has not executed since the previous patch; if it is only reached during startup, compile instead." This alone would have prevented the second lap of the trap.

Severity

Tester-scored 4/10 (guidance gap, not misbehavior); 3 real wasted round trips in one session. No false statement in the response — filed as an improvement, not a bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions