## 1. Core Command Infrastructure

- [x] 1.1 Create `src/core/CommandHistory.h` — define `ICommand` pure-virtual interface (`Execute`, `Undo`, `GetDescription`) and `CommandHistory` class with `Push`, `Undo`, `Redo`, `Clear`, `CanUndo`, `CanRedo`, `GetUndoDescription`, `GetRedoDescription`
- [x] 1.2 Create `src/core/CommandHistory.cpp` — implement `CommandHistory` with undo/redo stacks (`std::vector<std::unique_ptr<ICommand>>`); `Push` executes command, pushes to undo stack, clears redo stack
- [x] 1.3 Add `CommandHistory` as a member of `Application` and pass `CommandHistory*` into all panel and manager constructors/init methods
- [x] 1.4 Call `m_commandHistory.Clear()` inside `Application::RefreshManagers()` so history resets on every stage lifecycle event
- [x] 1.5 Add `CMakeLists.txt` entries for all new source files (`CommandHistory.cpp` and all command `.cpp` files added in subsequent tasks)

## 2. Transform Commands

- [x] 2.1 Create `src/core/commands/TransformCommand.h/.cpp` — stores prim `SdfPath`, `SdfLayerHandle` edit target, and pre/post TRS (`GfVec3d` translate, `GfVec3f` rotate, `GfVec3f` scale); `Execute()` applies post-values, `Undo()` applies pre-values via `UsdGeomXformCommonAPI` + `UsdEditContext`
- [x] 2.2 Modify `TransformManipulator` — accept `CommandHistory*` in constructor/init; on drag-begin snapshot TRS into `m_dragStartTRS`; on drag-end (detect `wasDrawing && !m_isDragging`) push `TransformCommand` only when delta is non-zero
- [x] 2.3 Modify `PropertyPanel` — accept `CommandHistory*`; capture pre-edit TRS before field edit begins; push `TransformCommand` inside `ImGui::IsItemDeactivatedAfterEdit()` blocks for translate, rotate, and scale fields

## 3. Scene Hierarchy Commands

- [x] 3.1 Create `src/core/commands/CreatePrimCommand.h/.cpp` — stores `SdfPath`, `TfToken typeName`, `SdfLayerHandle`; `Execute()` calls `stage->DefinePrim`; `Undo()` calls `stage->RemovePrim`
- [x] 3.2 Create `src/core/commands/DeletePrimCommand.h/.cpp` — on construction serialises the target prim's spec via `SdfCopySpec` into an anonymous layer; `Execute()` removes the prim; `Undo()` restores from the anonymous layer via `SdfCopySpec`
- [x] 3.3 Create `src/core/commands/AddReferenceCommand.h/.cpp` — stores created prim path and `SdfReference`; `Execute()` wraps in Xform and adds reference; `Undo()` removes the prim
- [x] 3.4 Create `src/core/commands/ReplaceReferenceCommand.h/.cpp` — stores prim path, old `SdfReference`, new `SdfReference`; `Execute()` applies new reference; `Undo()` restores old
- [x] 3.5 Modify `SceneHierarchyPanel` — accept `CommandHistory*`; replace direct `Application::CreatePrimOnStage` calls with `Push(CreatePrimCommand)`; replace direct delete with `Push(DeletePrimCommand)`; replace `AddReferenceToStage` with `Push(AddReferenceCommand)`; replace `ProcessPendingReplaceRef` with `Push(ReplaceReferenceCommand)`

## 4. Attribute Edit Commands

- [x] 4.1 Create `src/core/commands/AttributeSetCommand.h/.cpp` — stores `std::string description`, `std::function<void()> executeFunc`, `std::function<void()> undoFunc`; captures old value before set using `UsdAttribute::Get<T>` at the call site
- [x] 4.2 Modify `PropertyManager::SetPropertyValue` and `SetPropertyValueInLayer` — read old value, construct `AttributeSetCommand` with closures for old/new applies, push to `CommandHistory`

## 5. Layer Operation Commands

- [x] 5.1 Create `src/core/commands/LayerCreateCommand.h/.cpp` — stores layer file path and insertion index; `Execute()` calls `LayerManager::CreateSublayer`; `Undo()` calls `LayerManager::RemoveSublayer`
- [x] 5.2 Create `src/core/commands/LayerRemoveCommand.h/.cpp` — stores layer path and original index; `Execute()` removes; `Undo()` re-inserts at saved index
- [x] 5.3 Create `src/core/commands/LayerReorderCommand.h/.cpp` — stores full ordered-path list before and after; `Execute()` applies new order; `Undo()` restores old order by rewriting `rootLayer->GetSubLayerPaths()`
- [x] 5.4 Modify `LayerPanel` — accept `CommandHistory*`; wrap Create, Remove, MoveUp, and MoveDown calls with the corresponding commands

## 6. Hotkeys and Menu Integration

- [x] 6.1 In `Application`'s main-loop (or `ImGuiContext`), detect `Ctrl+Z` and `Ctrl+Y` / `Ctrl+Shift+Z` key combinations when no ImGui text widget has input focus (`!ImGui::GetIO().WantTextInput`); call `m_commandHistory.Undo()` / `m_commandHistory.Redo()` accordingly
- [x] 6.2 Add **Edit** menu (or extend existing menu bar) with **Undo** and **Redo** items; display `GetUndoDescription()` / `GetRedoDescription()` in item labels; disable items via `ImGui::BeginDisabled(!CanUndo())` / `(!CanRedo())`

## 7. Build and Verification

- [x] 7.1 Run `cmake --preset default` and `cmake --build build --config Release` — compilation succeeds; LNK1104 only occurs because `UsdLayerManager.exe` is currently running (expected)
- [ ] 7.2 Run `cmake --install build --config Release` and launch `install/bin/App.exe`; manually verify: create a prim, undo removes it, redo restores it
- [ ] 7.3 Manually verify gizmo drag undo: translate a prim with the Move gizmo, press Ctrl+Z, confirm prim returns to original position
- [ ] 7.4 Run `ctest --test-dir build -C Release` and confirm all tests pass
