# Remorse First Class-Authoring Checklist ## Purpose This note turns the current class-lift preparation into a concrete execution checklist for the first real Ghidra/MCP authoring batch. It is intentionally operational. The goal is to remove startup cost once the necessary MCP class/vtable/datatype tools exist. ## Recommended First Pilot Order Current best pilot ranking: 1. `EntityDispatchEntry` 2. `SpriteNode` 3. `EntityVmOwnerResource` Why this order: - `EntityDispatchEntry` has strong ctor/release and field-group evidence - `SpriteNode` has a compact, visible virtual surface - `EntityVmOwnerResource` is structurally bounded but still slightly more loader-schema-sensitive ## Batch 0: Preconditions Before touching class ownership in Ghidra: 1. re-read [docs/remorse-class-lift-index.md](docs/remorse-class-lift-index.md) 2. re-read the target family note 3. confirm the ABI note and compatibility-header draft are still aligned with the intended source track 4. confirm the MCP tool surface actually supports namespace/class creation, datatype authoring, and method ownership changes Do not start with authoring if any of those are still missing. ## Batch 1: Authoring Rules These rules should hold for the first pilot family regardless of which family is chosen: 1. move only strongly owned methods first 2. preserve raw slot order in provisional vtables 3. keep uncertain fields explicit as padding or unknown words/bytes 4. prefer conservative owner names over polished but speculative subsystem names 5. add provenance comments when a layout or slot label is imported from an earlier note rather than re-derived in-session ## Pilot A: `EntityDispatchEntry` Use [docs/entity-dispatch-entry-class-layout.md](docs/entity-dispatch-entry-class-layout.md) as the source note. ### Minimum Ghidra/MCP deliverables 1. create owner namespace/class for the base family 2. create provisional instance struct for the base layout 3. create provisional vtable datatype with stable known slots only 4. move base ctor/release methods under that owner 5. keep subtype/overlay-specific methods outside the base owner until the split is tighter ### First methods to move - base ctor at `0008:ba00` - release/destroy surface at `0008:dbec` - runtime-state init/release pair `000d:7e00` / `000d:8078` only if the owner relationship is still judged direct in-session ### Fields that should stay visible immediately - type and subtype-related words near `+0x04/+0x06/+0x08` - active/hold/runtime flags around `+0x16/+0x18` - runtime-state and paired resource lanes around `+0x3c/+0x40` ### Things to avoid in the first pass - flattening every derived constructor into one base class - forcing final names for every slot in the vtable - pretending all runtime-state fields belong to the same subtype ## Pilot B: `SpriteNode` Use [docs/sprite-node-class-layout.md](docs/sprite-node-class-layout.md) as the source note. ### Minimum Ghidra/MCP deliverables 1. create owner namespace/class for `SpriteNode` 2. create provisional vtable with only the slot order and best current role labels 3. move destructor and event-dispatch surface under that owner 4. create instance struct with the known layout anchors and visible unknown regions ### First methods to move - `000b:326e sprite_node_destroy` - `000b:3ab2 sprite_node_dispatch_event` - `000b:3380 sprite_node_is_dirty` - `000b:33a6 sprite_node_mark_dirty` ### Things to avoid in the first pass - pushing traversal helpers into the class just because they walk the tree - overcommitting to child/sibling field semantics beyond the already-noted anchors ## Pilot C: `EntityVmOwnerResource` Use [docs/entity-vm-runtime-owner-resource-layout.md](docs/entity-vm-runtime-owner-resource-layout.md) as the source note. ### Minimum Ghidra/MCP deliverables 1. create helper class owner 2. create compact helper instance struct 3. create provisional method table for the `+0x04` and `+0x0c` helper callbacks 4. move create/destroy pair under that owner ### Things to avoid in the first pass - baking in final file-family schema labels - collapsing the helper into the runtime object as anonymous fields ## Source-Emission Readiness Gate Do not emit the first C++ skeleton immediately after Ghidra authoring. Only emit when all of these are true: 1. owner namespace/class exists 2. provisional instance struct exists 3. provisional vtable exists when relevant 4. top 3-5 strongly owned methods are moved 5. unresolved fields remain explicit instead of silently renamed away 6. Track A versus Track B assumptions are recorded for that family ## Success Criteria For The First Real Batch The first class-authoring batch is successful if: 1. one family becomes visibly easier to navigate in Ghidra 2. method ownership is improved without speculative over-grouping 3. instance layout is more explicit than raw offset math 4. the result can drive one hand-maintained C++ header/source skeleton with the compatibility layer ## Bottom Line The first class-authoring batch should be judged by structural clarity, not by how polished or object-oriented the output looks. `EntityDispatchEntry` remains the best first pilot because it offers the highest ratio of stable object evidence to remaining subtype ambiguity.