# Step 3: domain-property-ownership ## Read First Read these files before editing: - `/AGENTS.md` - `/docs/AGENT_RULES.md` - `/docs/implementation-plans/property-model-foundation-implementation-plan.md` - `/include/fesa/core/Domain.hpp` - `/src/core/Domain.cpp` - `/include/fesa/property/Property.hpp` - `/include/fesa/property/ShellProperty.hpp` - `/tests/core/domain_storage_test.cpp` - `/tests/core/domain_model_object_test.cpp` ## Task Make `Domain` own runtime property objects through the `Property` base class. Required API shape: - `void Domain::addProperty(std::unique_ptr property);` - `const fesa::property::Property* Domain::findProperty(PropertyId id) const noexcept;` - `const fesa::property::Property& Domain::property(PropertyId id) const;` - `std::size_t Domain::propertyCount() const noexcept;` Compatibility helpers may remain if useful: - `addShellProperty(std::unique_ptr)` - `findShellProperty(PropertyId)` - `shellProperty(PropertyId)` - `shellPropertyCount()` Rules: - Property storage must be `std::unique_ptr`. - Reject null property pointers. - Reject duplicate property ids. - For `ShellProperty`, reject missing material id. - `Domain::addElement` must validate `Element::propertyId()` using runtime property storage. ## Tests To Write First - Rewrite relevant property assertions in `/tests/core/domain_storage_test.cpp` to use runtime property ownership. - Add a test that `const Domain::property(id)` returns `const Property&`. - Preserve direct `ShellProperty` lookup for now if compatibility helpers remain. ## Acceptance Criteria ```powershell ctest --test-dir build/msvc-debug --output-on-failure -C Debug -R "domain|model-object" python scripts/validate_workspace.py ``` ## Verification Notes 1. Run targeted CTest before production edits and confirm failure. 2. Do not add solver vectors, equation ids, or integration-point state to `Domain`. 3. Update `phases/property-model-foundation/index.json` for this step result.