docs: add agent skill guides and update CMake build instructions

This commit is contained in:
AndreaRigoni
2026-04-17 09:36:24 +00:00
parent 1288fc3a41
commit bca63a7fc8
10 changed files with 521 additions and 26 deletions

View File

@@ -1,6 +1,10 @@
# Skill: Build uLib with Micromamba
---
trigger: always_on
---
This skill provides instructions for building the uLib project using the micromamba environment.
# Rule: Build uLib with Micromamba
This rule provides instructions for building the uLib project using the micromamba environment.
## Context
- **Environment**: micromamba `uLib`
@@ -14,26 +18,27 @@ This skill provides instructions for building the uLib project using the microma
```bash
export MAMBA_EXE="/home/share/micromamba/bin/micromamba"
export MAMBA_ROOT_PREFIX="/home/share/micromamba"
eval "$(/home/share/micromamba/bin/micromamba shell hook --shell bash)"
export PRESET="clang-make"
eval "$(${MAMBA_EXE} shell hook --shell bash)"
micromamba activate uLib
```
2. **Full Rebuild (if needed)**:
If the `build` directory does not exist or a full reconfiguration is required:
```bash
conan profile detect --force
conan install . --output-folder=build --build=missing
cmake --preset conan-release
conan install . --output-folder=build/${PRESET} --build=missing --profile=fast
cmake --preset ${PRESET}
cmake --build build/${PRESET} -j$(nproc)
```
3. **Incremental Build**:
Run the build command from the root directory, pointing to the `build` folder and using all cores.
```bash
cmake --build build -j$(nproc)
cmake --build build/${PRESET} -j$(nproc)
```
4. **Specific Target Build**:
4. **Specific Target Build - gcompose**:
To build a specific target (e.g., gcompose):
```bash
cmake --build build --target gcompose -j$(nproc)
```
cmake --build build/${PRESET} --target gcompose -j$(nproc)
```

View File

@@ -0,0 +1,49 @@
# Skill: Core Object & Property System
This skill defines the patterns for implementing and working with the `uLib` core object model.
## Context
- **Base Class**: `uLib::Object`
- **Property System**: `uLib::Property<T>`
- **Registration**: All objects must register their properties for UI visibility and serialization.
## Implementation Patterns
### 1. Defining an Object
Inherit from `uLib::Object` and use the `ULIB_PROPERTY` macro for members.
```cpp
class MyObject : public uLib::Object {
public:
ULIB_PROPERTY(double, Speed, 0.0)
ULIB_PROPERTY(std::string, Description, "None")
MyObject() {
// Required for property visibility in PropertyEditor
ULIB_ACTIVATE_PROPERTIES(*this)
}
};
```
### 2. Property Access
Properties can be treated like their underlying types or accessed via `.Get()`/`.Set()`.
```cpp
obj.Speed = 10.5; // Triggers Updated() signal
double s = obj.Speed; // Implicit conversion
obj.Speed.SetRange(0.0, 100.0); // Setting metadata
```
### 3. Serialization
Implement `serialize` overloads for different archive types. Use `hrp` (Human Readable Property) to name fields.
```cpp
template <class ArchiveT>
void serialize(ArchiveT &ar, const unsigned int version) {
ar & boost::serialization::make_nvp("InstanceName", this->GetInstanceName());
ar & boost::serialization::make_hrp("Speed", Speed, "m/s");
}
```
## Checklist
- [ ] Inherit from `uLib::Object`.
- [ ] Use `ULIB_PROPERTY` for members that should appear in the GUI.
- [ ] Call `ULIB_ACTIVATE_PROPERTIES` in the constructor.
- [ ] Implement `serialize` if persistence is required.

View File

@@ -0,0 +1,39 @@
# Skill: HEP/Geant Simulation Rules
This skill provides instructions for developing the Geant4 simulation components within `uLib`.
## Context
- **Domain Objects**: `Material`, `Solid`, `LogicalVolume`, `PhysicalVolume`.
- **Integration**: `mutomGeant` library wraps Geant4 classes into `uLib::Object`s.
## Patterns
### 1. Adding a New Solid
New solids must implement `GetPolyhedron()` to support VTK visualization.
```cpp
G4Polyhedron* MySolid::GetPolyhedron() const {
// Return the tessellated representation of the Geant4 solid
return m_G4Solid->GetPolyhedron();
}
```
### 2. Physical Volume Hierarchy
Maintain the relationship between `PhysicalVolume` and its parent `LogicalVolume`.
```cpp
auto* world = new LogicalVolume(worldSolid, worldMat);
auto* detector = new PhysicalVolume(detectorLogic, world, "Detector1");
detector->SetPosition({0, 0, 100}); // Relative to parent
```
### 3. Transformation Synchronization
Use the centralized `TRS` object to manage position and rotation. Synchronization with Geant4's internal stores should be reactive.
- Listen to `Object::Updated` on the `Solid` or `PhysicalVolume`.
- Update the underlying `G4VPhysicalVolume` position/rotation.
## Material Management
Use the `Matter` class to manage Geant4 materials. Ensure materials are registered in the `G4NistManager` or custom material store if needed.
## Checklist
- [ ] Does the solid implement `GetPolyhedron()`?
- [ ] Are parents correctly assigned in `PhysicalVolume` constructors?
- [ ] Is the `TRS` object used for all spatial transformations?

View File

@@ -0,0 +1,40 @@
# Skill: Memory Management & Object Lifecycle
This skill provides guidelines for managing memory safely within the `uLib` framework to prevent memory corruption and leaks.
## Context
- **Ownership**: `ObjectsContext` typically owns its children.
- **Shared Access**: Use `SmartPointer<T>` for objects shared across multiple systems (e.g., Geant4 and VTK).
- **Core Principle**: Avoid manual `delete` on objects managed by the framework.
## Patterns
### 1. Context Ownership
When an object is added to an `ObjectsContext`, it is managed by that context.
```cpp
auto* context = new ObjectsContext();
auto* obj = new MyObject();
context->AddObject(obj);
// Do NOT delete obj; it will be deleted when context is destroyed.
```
### 2. Smart Pointers
Use `SmartPointer<T>` for resources like `Material` or `Solid` that are used by both domain logic and external engines (Geant4).
```cpp
uLib::SmartPointer<Material> mat = new Material("Lead");
solid->SetMaterial(mat); // Shared ownership
```
### 3. Geant4 Object Safety
Geant4 often takes ownership of certain objects (like `G4VPhysicalVolume`). When wrapping these:
- Ensure the wrapper doesn't double-free the Geant4-owned pointer.
- Use `recursion_guard` if synchronizing transformations between `uLib::Object` and Geant4 volumes to prevent signal loops.
## Debugging Memory Issues
- **SIGABRT (invalid pointer)**: Usually caused by deleting an object that was already managed (and deleted) by an `ObjectsContext` or `SmartPointer`.
- **Leaks**: Check if objects were created but never added to a context or wrapped in a `SmartPointer`.
## Checklist
- [ ] Are objects added to an `ObjectsContext`?
- [ ] Is `SmartPointer` used for shared resources?
- [ ] Is there a risk of double-freeing Geant4-managed pointers?

View File

@@ -0,0 +1,34 @@
# Skill: Multi-System Signaling (uLib ↔ Qt)
This skill manages the coexistence of `uLib::Object` signals and Qt's `Q_OBJECT` signaling system.
## Context
- **uLib Signals**: Used for domain logic and data changes (`uLib::Object::connect`).
- **Qt Signals**: Used for UI events, widgets, and application-level control flow (`QObject::connect`).
## Patterns
### 1. Bridging Logic
When a domain change needs to trigger a UI update, use a wrapper or a direct connection if the widget has access to the `uLib::Object`.
```cpp
// In a Qt Widget
uLib::Object::connect(domainObj, &Object::Updated, [this]() {
this->update(); // Trigger Qt repaint
});
```
### 2. Selection Flow
Selection usually starts in the VTK Viewport (Qt) and flows to the domain context.
1. `QViewport` emits `prop3dSelected(Prop3D*)` (Qt signal).
2. `MainPanel` catches it and calls `contextPanel->selectObject(p->GetContent())`.
3. `ContextPanel` updates the tree view and property editors.
### 3. Connection Hygiene
- Use `uLib::Object::connect` for everything involving `uLib::Property` changes.
- Use Qt `connect` for button clicks, menu actions, and window events.
- Be careful with lambda captures; ensure the captured object is still alive or use weak pointers if necessary.
## Checklist
- [ ] Is the correct signaling system being used for the task?
- [ ] Are capture groups in lambdas safe?
- [ ] Does selection flow correctly between the 3D view and the tree view?

View File

@@ -0,0 +1,34 @@
# Skill: Standardized Testing & Validation
This skill provides the standard workflow for testing and validating changes in the `uLib` project.
## Context
- **Tooling**: `ctest` and direct execution of test binaries in the `build/` directory.
- **Location**: Test binaries are typically located in `build/src/*/testing/` or `build/Testing/`.
## Workflow
### 1. Running All Tests
From the root directory:
```bash
ctest --test-dir build/clang-make --output-on-failure
```
### 2. Running Component Tests
Run specific categories of tests:
- **Core**: `./build/clang-make/src/Core/testing/CoreTest`
- **Math**: `./build/clang-make/src/Math/testing/MathVectorTest`
- **Geant**: `./build/clang-make/src/HEP/Geant/testing/GeantApp`
- **VTK**: `./build/clang-make/src/Vtk/testing/vtkViewerTest`
### 3. Debugging a Failing Test
Run the binary directly through `gdb` or `valgrind` (if available):
```bash
gdb --args ./build/clang-make/src/Core/testing/ObjectWrapperTest
```
## Validation Checklist for New Features
- [ ] Does `ctest` pass globally?
- [ ] If changing visualization, does `vtkViewerTest` show the correct results?
- [ ] If changing Geant logic, does `GeantApp` run without memory aborts?
- [ ] Are new tests added to the appropriate `CMakeLists.txt`?

View File

@@ -0,0 +1,52 @@
# Skill: VTK Visualization Pipeline
This skill defines how to bridge domain objects with the VTK 3D visualization layer.
## Context
- **Wrapper**: `Prop3D` (wraps a `vtkProp`).
- **Mapping**: `Viewport` maintains `m_ObjectToProp3D` for synchronization.
- **GUI Integration**: `QViewport` handles Qt events and selection signals.
## Implementation Patterns
### 1. Creating a Prop3D
A `Prop3D` should wrap a domain object and update its visual state when the object changes.
```cpp
class MyProp3D : public Prop3D {
public:
MyProp3D(MyObject* obj) : Prop3D(obj) {
// Connect domain updates to visual refreshes
uLib::Object::connect(obj, &Object::Updated, [this]() { this->SyncFromObject(); });
// Expose properties to the VTK side-panel
ULIB_ACTIVATE_DISPLAY_PROPERTIES(*this)
}
void SyncFromObject() {
// Update VTK actors/mappers from MyObject's properties
}
};
```
### 2. Display Properties
Use `serialize_display` to choose which properties of the domain object or the `Prop3D` itself are visible in the sliding "Display Properties" panel in `gcompose`.
```cpp
void serialize_display(Archive::display_properties_archive &ar) {
ar & boost::serialization::make_hrp("Opacity", m_Opacity);
ar & boost::serialization::make_hrp("Wireframe", m_Wireframe);
}
```
### 3. Transformation Sync (TRS)
Always synchronize the object's `trs` (Translate, Rotate, Scale) with the VTK actor's user transform.
```cpp
void UpdateTransform() {
auto matrix = GetContent()->GetTransform().GetMatrix();
m_Actor->SetUserMatrix(uLib::ToVtkMatrix(matrix));
}
```
## Checklist
- [ ] Does the `Prop3D` connect to the object's `Updated()` signal?
- [ ] Are `ULIB_ACTIVATE_DISPLAY_PROPERTIES` and `serialize_display` implemented?
- [ ] Is the transformation (TRS) correctly mapped to the VTK actor?